bobcat-3.19.01/CLASSES0000644000175000017500000000204412257522663013135 0ustar frankfrank# Classes compiled from icmake/special: xpointer, milter, ssl, readline a2x align arg argconfig autoptr base64streambufbase binarysearch binops cgi cidr clientsocket cmdfinder cmdfinderbase configfile datetime errno exception fbb fnwrap foreach fork fswap gethostent glob gs hash hostent hostname ibase64stream ibase64streambuf ifdstream ifdstreambuf ifilterstreambuf indent inetaddress iostream iostreambuf irandstream isharedstream iuo lc level localclientsocket localserversocket localsocketbase log logbuffer mailheaders mbuf msg mstream multistreambuf ofdstream ofdstreambuf ofilterstreambuf ofoldstream ofoldstreambuf ohexstreambuf onekey osharedstream pattern pf_iterator pf_iteratorstream pipe primefactors processenums processdata process ptriter randbuffer ranger redirector refcount repeat selector serversocket sharedblock sharedmemory sharedmutex sharedpos sharedsegment sharedstream sharedstreambuf signal socketbase stat string stringline syslogbuf syslogstream table tablebase tablebuf tablelines tablesupport tempstream typetrait user x2a bobcat-3.19.01/INSTALL0000644000175000017500000000600112222576540013136 0ustar frankfrankTo Install the bobcat library by hand instead of using the binary distribution perform the following steps: 0. The previously used scripts below make/ are obsolete and were removed from this and future distributions. Icmake should be used instead, for which a top-level script (build) and support scripts in the ./icmake/ directory are available. Icmake is available on a great many architectures. See the file INSTALL (and INSTALL.im, replacing the previously used INSTALL.cf) for further details. 1. Inspect the values of the variables in the file INSTALL.im Modify these when necessary. 2. Inspect the path to icmake in the `build' script. By default it is /usr/bin/icmake, but some installations use /usr/local/bin/icmake Adapt where necessary. 3. Run ./build libraries to compile the bobcat libraries. Optionally add the argument 'strip' if you want the libraries to be stripped. Unless you need the symbolic information in the compiled object modules, it is probably a good idea to provide this argument. So in that case issue: ./build libraries strip If you want to add the Milter and Xpointer classes, issue ./build libraries all or ./build libraries all strip If `all' is omitted, you will be asked interactively which of the two classes (if any) should be added to the libraries. To compile the Milter class you need the header libmilter/mfapi.h, which is (in Debian) part of the libmilter-dev package. To compile Xpointer, you need X11/Xlib.h, which is (in Debian) part of the libx11-dev package. If you don't intend to write programs using these classes, it's ok not to include these classes into the library, since no other classes depend on these two (see README.class-setup). 4. Run ./build lcgen to build the bobcatlcgen program 5. Run (probably as root) ./build install to install. Optionally add two additional argument as a base directories below which respectively the run time (shared) library documentation and the development files plus static library documentation will be installed. Following the installation nothing in this directory tree is required for the proper functioning of the bobcat library, so consider removing it. Make sure that the library is found by the loader. By default it is installed in /usr/lib, which is in the loader's standard search path By default the headers are stored under /usr/include. Since this is part of the compiler's the standard include path the header files are included as, e.g., #include . No `bobcat' headers have (.h) extensions. By default the manual pages are stored under /usr/share/man/man1, /usr/share/man/man3, and /usr/share/man/man7, which are normally in the `man' program's set of visited directories. bobcat-3.19.01/INSTALL.im0000644000175000017500000001042512257522663013554 0ustar frankfrank // About compiling the bobcat library on BSD/MacOSX: // // According to Karel Kubat (karel at e dash tunity dot com) the bobcat // library won't compile under BSD/MacOSX if the Linux options to create // the dynamic library are used. Instead of // -shared -Wl,-z,def,-soname, // Karel suggests to use: // -dynamiclib -Wl,-single_module // // Also, he suggests to use the name libbobcat.dylib instead of // libbobcat.so.1 // // In the directory ./contrib the script c-conf is found which is provided // by Karel and which might be useful to construct the libraries under // BSD/MacOSX systems. Don't contact me if you experience any problems // with Karel's script. Instead, contact Karel directly. //#define ONLY_STATIC // When compiling Bobcat for e.g., CYGWIN under Windows, activate the // above #define: it prevents the construction of the shared library #define CXX "g++" #define CXXFLAGS "--std=c++0x -O2 -g -Wall" // Specify compiler options that should be used. // This is overruled by the environment variable CXXFLAGS // The options "-isystem tmp" must always be used, are set in // icmake/library and should not be altered. #define PTHREAD "sharedmutex sharedblock sharedmemory sharedsegment " \ "process processdata" // Classes requiring -lpthread #define LDFLAGS "-lpthread" // Specify linker options that should be used when creating the shared // library #define LIBRARIES // Install the libraries, remove if not requested #define HEADERS // Install the headers, remove if not requested #define MANPAGES // Install the manpages, remove if not requested #define MANHTML // Install the html-versions of the manpages, remove if not requested #define DOCOTHER // Install remaining docs (README, examples, etc), remove if not requested // The following /bin/cp options are used to keep, rather than follow // symbolic references. If your installation doesn't support these flags, // then change them into available ones. // -P, --no-dereference // never follow symbolic links in SOURCE // --preserve[=ATTR_LIST] // preserve the specified attributes (default: // mode,ownership,timestamps), if possible additional // attributes: context, links, all // -d same as --no-dereference --preserve=links #define CPOPTS "-d" // The following icmake string variables are given their values below, in // the function `setLocations()' string BASE; // BASE=is the directory below which ALL bisonc++ files will be stored. // For an operational non-Debian installation, you probably must be // `root', and BASE "/usr" or BASE "/usr/local" is suggested (see // below). `BASE' itself is not used outside of this file, so feel free to // define BIN, SKEL, MAN and DOC (below) in any which way you like. string BIN; // The location of the binary program bobcatlcgen //string GPP; // GPP specifies the compiler to use. By defining GPP with a specific // version (e.g., GPP=g++-4.1) that particular version can be used. The // distributed definition uses the `default' compiler version and uses // `g++'. It is `gpp' in some installations. string DOC; // DOC is the directory in which all standard documentation will be stored // in this directory the non-development related information is stored. It // is not used if not defined (or defined empty) string DOCDEV; // DOCDEV is the directory in which all other documentation will be stored // In this directory the development related information is stored string INC; // the directory in which the header files will be stored string LIB; // the directory in which the bobcat libraries will be stored string MAN; // MAN is the directory in which the manual pages will be stored // They are stored below man3 and man7 string SHAREDOPT; string SHAREDLIB; void setLocations() { BASE = "/usr"; BIN = BASE + "/bin"; DOC = BASE + "/share/doc/libbobcat3"; DOCDEV = BASE + "/share/doc/libbobcat3-dev"; INC = BASE + "/include/bobcat"; LIB = BASE + "/lib"; MAN = BASE + "/share/man"; } bobcat-3.19.01/LICENSE0000644000175000017500000010471612260244322013116 0ustar frankfrank GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state 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 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . Specific permission is granted for the GPLed code in this distribution to be linked to OpenSSL without invoking GPL clause 2(b). bobcat-3.19.01/READLINE0000644000175000017500000000012712222576537013224 0ustar frankfrank# This file is read from icmake/special readlinebuf readlinehistory readlinestream bobcat-3.19.01/README0000644000175000017500000000276512222576534013005 0ustar frankfrank BOBCAT Brokken's Own Base Classes And Templates This library contains C++ classes (and header files) I frequently use in my programs. Practically all its entities are defined in the namespace FBB. Those that are not are, e.g., overloaded versions operator<<, which should normally be defined as a free function. To use the library in your programs, add `-lbobcat' to your link-command, to include a header file for the class `Class' include 'bobcat/class' unless advised otherwise. To compile and install this library unpack the tar.gz file, and follow the instructions in the INSTALL file. If you want to use the .deb precompiled binaries, do as follows: - to use the bobcat library to run executables depending on the bobcat shared library, bobcat_*.deb must be installed. - to compile programs using the bobcat library, and to have the class-manual pages you must install the bobcat-dev_*.deb package. This distinction is not made if you compile and install the bobcat library yourself. When installing the bobcat-dev*.deb version, or when installing bobcat according to the instructions in the INSTALL file, accepting the settings in INSTALL.im, - html versions of the manual pages are found in the directory /usr/share/doc/bobcat-dev/man/ - man bobcat - will show the main class-index - man -e bobcat xxx - shows the man-page for class `xxx' Frank f.b.brokken@rug.nl bobcat-3.19.01/README.X110000644000175000017500000000273212222576531013344 0ustar frankfrankWhen using the X11 library (which may be implied, e.g., when linking the GTK library) in combination with Bobcat, make sure the X11 library is passed to the linker before the bobcat library is specified. E.g., use -lX11 -lbobcat If the bobcat library is specified before the X11 library the following stand-in functions defined in the bobcat library will be used: `XOpenDisplay' `XCloseDisplay' `XFlush' `XWarpPointer' `XQueryPointer' `XGetWindowAttributes' These symbols were included in the bobcat library to prevent `undefined reference' linker errors from being generated when shared libraries are used but the X11 library is *not* used. What happens when X11 is specified before bobcat is that although the bobcat library defines stand-in functions they are presented to the linker only after the linker has seen the similarly named symbols in the X11 library. The linker uses the symbols first encountered, and will therefore properly use the symbols defined in the X11 library. However, if the X11 library is not used (e.g., Xpointer is not used) and if bobcat itself would not define the above symbols then those symbols would not be defined in the shared libraries inspected by the linker, producing linker errors. Although these errors could be prevented by specifying the option -Wl,--allow-shlib-undefined requiring this option seems like a more complex instruction than requiring that when using the X11 library it must be specified before the bobcat library. bobcat-3.19.01/README.class-setup0000644000175000017500000002153312242116056015230 0ustar frankfrankThe following diagram shows the class dependencies. Classes listed on the same line have no mutual dependencies. Classes listed on lines starting with the digit 0 are not depenent on other bobcat classes. Then, diagrams showing dependencies of other classes. Dependencies should be read upwards, e.g., String depends on A2x, Hostname depends on Hostent and Exception. Dependencies refer to the construction of the class members as well as the use of the class headers. So, when compiling the class Msg the class Exception must be available (if not compile-time then most likely run-time). The dependencies are not necessarily related to inheritance. The file CLASSES lists all classes, in something resembling the order of addition of the classes to the Bobcat library. The classes `Milter' and `Xpointer' are optionally compiled, and are therefore not listed in the CLASSES file. The label IUO does not refer to a class but to functions defined in the FBB namespace for internal use only. They are declared in the bobcat/iuo header. Entries below, tagged with `(cont)' were mentioned earlier in the next hierarchy. Entries tagged with (Obs) are obsolete and should no longer be used. 0 X2a Hash Hostent TypeTrait Swap Indent ReadLineHistory | +-----+------+ | | binops repeat 0 MultiStreambuf SyslogBuf ReadLineBuf RandBuffer | | | SyslogStream ReadLineStream IRandStream | | 0 DateTime Exception IFilterStreambuf | | | | | +-----+---------+------+----------+ | | | | | | | | | User Signal | | +----+----+------+ | | | | | | | | +---------+ Mbuf EncryptBuf SharedMutex | | | | | | | | BigInt | Mstream SharedBlock | | | | | | +-----+ | SharedSegment | | | | | | | | | SharedEnum__ SharedPos +-------+ | | | | | | | +------+--------+ | PrimeFactors | | | | SharedMemory | GS__ | | | | | SharedStreambuf +----+ | | | | +------------+-------------+ | | | | | | | ISharedStream OSharedStream SharedStream Stat | | | Glob | LogBuffer +--------+-------+------+------+-----+-------------+ | | | | | | | | | | Pattern OneKey | | | +--+--+ | | | | | | +--------+ DecryptBuf | | Log | | | | Hostent | | | | | (cont) level ConfigFile | | | | | | +---+--+ | | | | | Hostname GetHostent | | LocalSocketBase InetAddress | | | SocketBase +-------------------+ | | | | LocalClientSocket LocalServerSocket +------+---------+ | | ClientSocket ServerSocket Exception(cont) | 0 +---------+--------+----+----+-----+------+----------+ IOStreambuf | | | | | | | | | Xpointer MailHeaders Milter | Pipe Fork Selector Redirector IOStream | | | | | | | +-----+------+----------+---------+ | | | | +------+ | | | | TempStream | | | | 0 A2x | | | | | String | +----+ | | | +--------+----+ | | | | | | | +---+----+ | | | | | | | Arg ConfigFile | | | | (cont) | | | | | | CmdFinderBase | +---+---+ | | | | | | | ArgConfig | | | | CmdFinder +----+-------------+ | | A2x(cont) | | | | 0 OFdStreambuf | IFdStreambuf | OFilterStreambuf | | | | | | | | | +---+ | | | | | | | | | +---+ | | | | | | | | | OHexStreambuf | lm mlm | | | | | | | +-------+ | +----+ | +-------+------+---+ | | | | | | | OFdStream +-------+--+--------+ IFdStream | | | | OFoldStreambuf Process | | | | | OFoldStream Exception(cont) | | | +----+----+ | +-----+-----+ | | DigestBuf HMacBuf 0 Align StringLine Exception(cont) | | | | +------------+ TableSupport | | Cidr +----------+ | | String (cont) TableBase TableLines | | +----+ +----+----+ | | | | | +-----+ | | | | | Table TableBuf | | | Stat(cont) Pattern(cont) X2a(cont) | | | | +-------+-----------+-----+------+ | | CGI bobcat-3.19.01/README.fnwrap0000644000175000017500000003301412222576532014266 0ustar frankfrankFnWrap: new implementation (as of Bison 2.15.00) FnWrap's new implementation reduces its size to slightly less than 50% of its previous size: from over 415 lines to 200. What follows is a description of its inner workings. All function implementations are given as in-class implementations. In Bobcat's FnWrap class all implementations were moved out of the the class interfaces, keeping the interfaces as clean as possible. Almost all of the functionality is encapsulated in the class FnWrap, as before. Although the FnWrap::unary and FnWrap::binary functions remain in existence, their implementations are now identical. In fact, their use is discouraged, promoting the use of the free function FBB::context instead. To start out, the class FnWrap defines several support structs that are not made visible outside of FnWrap. They are: template struct Dissect {}; template struct Dissect { typedef Ret ReturnType; }; The struct Dissect's specialization may receive any function pointer and determines the function's return type. The function's return type may then be obtained from the type ReturnType, defined by Dissect. In addition to determining a function's return value Dissect is also used to define a stand-in type for unary functors. Here care must be taken that no user-software can use this type to avoid confusion. By putting Dissect in FnWrap's private section user software cannot use this stand-in type, which is defined as a pointer type using the typedef: typedef Dissect *NotUsed; The second support struct is: template struct At { typedef typename std::tuple_element::type Type; }; This is a simple typework-saving struct, allowing the retrieval of the type of count's tuple's argument. It expects a count, which is converted to the corresponding index. FnWrap's core business is found in its nested struct Functor. Functor defines a unary or binary function object. The unary or binary function object is typically used by a generic algorithm. FnWrap::Functor objects are created (returned) by FBB::context, and also by the functions FBB::FnWrap::unary and FBB::FnWrap::binary. These three functions have identical implementations. FnWrap::unary and FnWrap::binary remain available for reasons of backward compatibility, their use is discouraged from now on, and they are no longer referred to in this description. FBB::context is a free (classless) function, having the following implementation: template FnWrap::Functor context(Function fun, Args &&...args) { return FnWrap::Functor (fun, std::forward(args) ...); } The function FBB::context receives the address of a Function, as well as any number of additional arguments. Since this is a function template, callers noramlly do not have to specify any of the types, as function templates are usually able to determine the types themselves. Having determined Function and the parameter pack's types, these are used to construct a matching FnWrap::Functor object, whose constructor receives the function's address (i.e., fun) and all remaining perfectly forwarded arguments that were used when calling FBB::context. Here FBB::context's work ends. Its purpose in life is to make a unary or binary function object available. By returning an FnWrap::Functor it has fullfilled that purpose. FnWrap::Functor is a nested struct in FnWrap's public section. Functor determines the function's return type (defining it as its RetType type) and its constructor saves the function's address in its d_function data member. In addition, it saves any remaining arguments received by the constructor in a tuple d_args, again perfectly forwarding the arguments originally passed to FBB::context. FnWrap::Functor's outline and constructor look like this: template struct Functor { typedef typename Dissect::ReturnType RetType; Function d_function; std::tuple d_args; Functor(Function fun, Args &&... args) : d_function(fun), d_args(std::forward(args)...) {} // two members, see below }; Functor defines two member templates: a unary and binary function call operator. Since they are member function templates they can determine the types of their arguments when they are actually called. Here are their implementations: The unary function: template typename Functor::RetType operator()(Arg1 &&arg1) { return CallPack >::call(d_function, std::forward(arg1), 0, d_args); } The binary function: template typename Functor::RetType operator()(Arg1 &&arg1, Arg2 &&arg2) { return CallPack>::call(d_function, std::forward(arg1), std::forward(arg2), d_args); } These members merely pass their arguments, as well as the values of Functor's data members d_function and d_args, to a static function 'call', defined in the CallPack struct. The real meat of what happens inside FnWrap becomes apparent when we turn our attention to CallPack. The CallPack struct has two tasks: * First, it must unpack tuple's arguments so they can be passed as arguments instead of a tuple to the function that is passed to its call member; * Second, it must call 'd_function' with the appropriate arguments. Whereas packing (variadic) arguments into a tuple is not difficult, unpacking a tuple back into a parameter pack is not a trivial tasks. CallPack uses the following algorithm: Initially there is a tuple, there are 'size' elements in the tuple and there is an empty parameter pack. Tuple element [size - 1] is obtained, and prepended to the parameter pack while recursively calling the function call. At each recursion size - 1 is passed to the recursive call as well, so 'size' eventually decays to 0. Once size has decayed to 0, a non-recursive partial specialization is selected by the compiler which will call the function (d_function), passing it arg1, arg2 (for binary functors), and the perfectly forwarded arguments of the parameter pack, which now contains all the arguments found in tuple. In addition to passing the correct arguments to d_function, CallPack also defines the types first_argument_type and second_argument_type, which are required by some generic algorithms. Here is the setup of struct CallPack, and its generic (recursive) call member: template struct CallPack: public CallPack::Type, Args ...> { typedef typename TypeTrait::Plain first_argument_type; typedef typename TypeTrait::Plain second_argument_type; typedef typename At::Type LastType; static RetType call(Func fun, Arg1 &&arg1, Arg2 &&arg2, Tuple &&tuple, Args &&...args) { return CallPack::call(fun, std::forward(arg1), std::forward(arg2), tuple, std::forward(std::get(tuple)), std::forward(args) ... ); } }; There's no CallPack object construction: the call function is static. It finds the type and value of the last not yet processed element in the tuple object and prepends that using perfect forwarding to the existing variable argument list, passing this series as the next variable argument list to the recursive all. Eventually all tuple's elements have been processed. As each recursive call reduces the size parameter by one, it will eventually decay to zero. At that point d_function can be called. Once size has reduced to 0 four situations must be distinguished, each using its own partial specialization of the member function 'call': * A void unary function was used. In this case Arg2 has type FnWrap::NotUsed, and RetType is void (remember that Functor's operator() members are called with either one or two arguments and that the unary Functor::operator() functions passes an FnWrap::NotUsed as Arg2 to CallPack::call). * A non-void unary function was used. In this case Arg2 has type FnWrap::NotUsed * A void binary function was used. In this case RetType is void. * A non-void binary function was used. Each alternative has its own specialization. Here are their implementations: * The void unary function (RetType is specified as void, Arg2 as FnWrap::NotUsed): template void CallPack::call( Func fun, Arg1 &&arg1, FnWrap::NotUsed &&arg2, Tuple &&tuple, Args &&...args) { fun(std::forward(arg1), std::forward(args)...); } * The non-void unary function (Arg2 is specified as FnWrap::NotUsed): template RetType CallPack::call( Func fun, Arg1 &&arg1, FnWrap::NotUsed &&arg2, Tuple &&tuple, Args &&...args) { return fun(std::forward(arg1), std::forward(args)...); } * The void binary function (RetType is specified as void): template void CallPack::call( Func fun, Arg1 &&arg1, Arg2 &&arg2, Tuple &&tuple, Args &&...args) { fun(std::forward(arg1), std::forward(arg2), std::forward(args)...); } * The non-void binary function: template RetType CallPack::call( Func fun, Arg1 &&arg1, Arg2 &&arg2, Tuple &&tuple, Args &&...args) { return fun(std::forward(arg1), std::forward(arg1), std::forward(args)...); } Now that we've designed and implemented FnWrap, here's how it can be used: Assume we have a class Strings having the following basic setup: class Strings { vector d_vs; public: Strings() : d_vs({"one", "two", "", "three"}) {} ... }; It simply defines a vector of strings: four elements, the 3rd one empty. All functions below are members, all implementations are given in-class: * Unary predicate: display all strings until the first empty one: void display(ostream &out) const { size_t nr = 0; find_if(d_vs.begin(), d_vs.end(), context(untilEmpty, nr, out)); } Using the following context-aware predicate function: static bool untilEmpty(string const &str, size_t &nr, ostream &out) { if (str.empty()) return true; // done out << ++nr << ' ' << str << '\n'; return false; // continue } * Unary functor: display all strings: void show(ostream &out) const { size_t nr = 0; for_each(d_vs.begin(), d_vs.end(), context(all, nr, out)); } Using the following context-aware void function: static void all(string const &str, size_t &nr, ostream &out) { out << ++nr << ' ' << str << '\n'; } * Binary predicate: count strings containing 't' void count() { size_t nLines = 0; cout << "Number of counts: " << count_if(d_vs.begin(), d_vs.end(), context(counter, cout, nLines)); cout << '\n' << nLines << " lines processed\n"; } Using the binary predicate function: static bool counter(string const &str, ostream &out, size_t &nLines) { out << "Line nr " << ++nLines << ": " << str; if (str.find('t') != string::npos) { out << ", contains 't'\n"; return true; } out << ", no 't'\n"; return false; } bobcat-3.19.01/README.immovable0000644000175000017500000000301712222576537014751 0ustar frankfrankCurrently immovable classes, hence classes using them will not offer move facilities: std::streambuf, std::ios Singleton classes are not provided with move facilities: there's never another object: arg argconfig Move aware classes: CGI CmdFinderBase CmdFinder ConfigFile Glob Hash Hostent MailHeaders Pattern Stat TableSupport TableLines User No need for move-operations (no class type data members, no move-operations defined in the base class, streams, or obsolete): Arg ArgConfig DateTime Errno FnWrap FnWrapXY (obsolete) Fork GetHostEnt Hostname Indent InetAddress Milter TableBase (used by classes derived fm streams) autoptr (obsolete) bigint decryptbuf digestbuf encryptbuf for_each fswap hmacbuf ifdstream ifdstreambuf iostream iostreambuf irandstream lc (obsolete) level localclientsocket localserversocket localsocketbase log logbuffer mbuf msg mstream multistreambuf ofdstream ofdstreambuf ofilterstreambuf ofoldstream ofoldstreambuf ohexstreambuf onekey pipe process randbuffer readlinebuf readlinehistory readlinestream redirector refcount repeat selector serversocket socketbase string syslogbuf syslogstream table tablebuf typetrait xpointer bobcat-3.19.01/README.milter0000644000175000017500000000253512222576534014273 0ustar frankfrankWhen using the milter library in combination with Bobcat, make sure the milter library is passed to the linker before the bobcat library is specified. E.g., use -lmilter -lbobcat If the bobcat library is specified before the milter library the following stand-in function defined in the bobcat library will be used: `smfi_register' This symbol was included in the bobcat library to prevent an `undefined reference' linker error from being generated when shared libraries are used but the milter library is *not* used. What happens when milter is specified before bobcat is that although the bobcat library defines a stand-in function it is presented to the linker only after the linker has seen the similarly named symbols in the milter library. The linker uses the symbols first encountered, and will therefore properly use the symbol defined in the milter library. However, if the milter library is not used (e.g., Milter is not used) and if bobcat itself would not define the above symbol then that symbol would not be defined in the shared libraries inspected by the linker, producing a linker error. Although the error could be prevented by specifying the option -Wl,--allow-shlib-undefined requiring this option seems like a more complex instruction than requiring that when using the milter library it must be specified before the bobcat library. bobcat-3.19.01/README.optimization0000644000175000017500000000754312222576534015531 0ustar frankfrank The `build' script uses -O3 as one of its compiler flags. Why -O3 and not -O2? (See also changelog 2.09.05 (2010/12/13) explaining why I reverted back to -O2) Compared to -O2, the compiler applies the following additional optimizations: -finline-functions Integrate all simple functions into their callers. The compiler heuristically decides which functions are simple enough to be worth integrating in this way. If all calls to a given function are integrated, and the function is declared "static", then the function is normally not output as assembler code in its own right. This is what we want for all class member functions defined inside their classes. These functions are always simple, consisting of at most one line of code. There are probably no other situations in this code for which the compiler will find it useful to integrate, but for the inline members. But in the case of the inline members (especially with the accessors) the overhead of the additional call seems to be needlessly spillfull. After all, C++ explicitly offers the in-class function definition for these kinds of functions, and thus, integrating their code rather than calling them seems like the right thing to do. -funswitch-loops Move branches with loop invariant conditions out of the loop, with duplicates of the loop on both branches (modified according to result of the condition). Since they're invariants, they can safely be moved, even though it will enlarge the code somewhat (because of the duplication). It prevents the code from testing a condition time and again for each individual iteration within a loop when that's not required. -fgcse-after-reload When -fgcse-after-reload is enabled, a redundant load elimination pass is performed after reload. The purpose of this pass is to cleanup redundant spilling. This refers to things like: removing dead code and reusing where possible values that can be proven to be already available in some registers. In `Contributions to the GNU Compiler Collection' the following paragraph is found: The first case, where redundant loads appear before register allocation, is handled by redundancy elimination optimization. Redundancy elimination removes redundant calculations of expressions by reusing previously calculated values that are stored in some register. The redundancy elimination pass of CCC did consider loading a calculation of an expression from memory, but did not consider store operations as expressions. Thus, GCC did replace a load following another load from the same memory location by a register copy, but did not replace a load following a store to the same location. We enhanced the redundancy elimination pass so that it would also consider stores as expressions, and hence replace subsequent loads from the same location with register copies. The second case of load-hit-store events was due to poor register spilling (i.e., the reload pass in GCC). (43) We handled this case in two ways. First, we added a "cleanup" pass after the reload that removed such redundancies, similar to the first case. However, this solution is limited because it works with hard (that is, allocated) registers. We reused the existing redundancy elimination infrastructure and added a special consideration of register availability for the register moves that we generate. We also took care of partial redundancy elimination by adding loads on basic blocks that are less critical (according to profiling), provided we can replace loads from critical blocks by register moves. Again, this optimization is considered a desirable one and thus it was decided to use -O3 rather than -O2. Frank. bobcat-3.19.01/README.process-pipe0000644000175000017500000000633412222576525015411 0ustar frankfrankThis file contains a description of the operations of the Process::operator| function. There is an accompanying file process-pipe.odp (and its pdf-equivalent: process-pipe.pdf) that illustrates the steps described below. Assuming we're calling (p1|p2|p3).start() and that p1 is defined with the CIN flag and p3 with the COUT flag, the following happens (the numbers refer to the odp slides / pdf pages): 1. P1 and P2 are passed to operator| as, resp. their lhs and rhs parameters. Process objects have two FBB::Pipe objects that are relevant here: oChildIn is the Pipe written to by the parent process and read by its child using stdin; iChildOut is the Pipe read by the parent process and written to by its child when writing its stdout. 2. operator| calls lhs.start(). Since lhs is the first process for which operator| is called (which can be deducted by operator| as lhs does not have the PIPE_IN flag set) it sets it CLOSE_ON_EXEC flag. This flag will cause lhs's oChildIn writing end of the pipe to close with future child processes. Why is this necessary? When later on the rhs process starts its child, it will contain a copy of all the parent's data. This includes, as lhs and rhs are both objects of the same main program, lhs's oChildIn. If lhs's oChildIn wouldn't be closed by rhs's child process then an open pipe to the lhs's child's input stream would remain available preventing the lhs's child process from ending at end-of-input. The start() function sets up the redirections: from the parent to its child, as shown in page/slide 2. 3. operator| copies lhs.iChildOut to rhs.oChildIn This too looks initially looks a but weird as an (for the parent) IN-pipe is copied to an OUT-pipe. However, when rhs.start() is called its child receives a copy of its parent oChildIn from which the child will read. So, the rhs parent never uses its oChildIn pipe for reading, but rhs's child process does. As rhs.oChildIn itself is lhs's iChildOut, rhs's child process will actually read the lhs's child process's output, setting up the pipe between lhs and rhs. 4. Next p2 and p3 are passed to operator|. Now p2 acts as lhs, p3 as rhs 5. operator| calls lhs.start() This is the point where lhs's child also receives p1's oChildIn pipe, which is now automatically closed due to its CLOEXEC flag. Note: not all operating systems, in particularly FreeBSD flavors, support the CLOEXEC fntl flag, even though it's been defined by POSIX since 2008. For those systems Process offers a work-around. The child redirections are standard, so the child reads oChildIn, which in fact is the output from p1's child; the parents obtains its child's output from its iChildOut pipe. 6. The lhs's iChildOut pipe is assigned to the rhs's oChildIn. Same reason as given at 3. 7. (p1|p2|p3).start() starts p3's child process. Once again the child process receives a copy of p1's oChildIn, which is again closed because of its CLOEXEC flag. Now, when the information inserted into p1 ends its oChildIn writing pipe is closed, informing p1's child that its input has been exhausted and the child process properly terminates. bobcat-3.19.01/SSLCLASSES0000644000175000017500000000024112222576524013511 0ustar frankfrank# This file is read from icmake/special bigint decryptbuf diffiehellman digestbuf encryptbuf hmacbuf isymcryptstream isymcryptstreambuf symcryptstreambufbase bobcat-3.19.01/TODO0000644000175000017500000000013012242373563012574 0ustar frankfrankProvide examples in the following man-pages: ifdstreambuf.yo milter.yo ofdstreambuf.yo bobcat-3.19.01/VERSION0000644000175000017500000000004112260244224013144 0ustar frankfrankVERSION=3.19.01 YEARS=2005-2013 bobcat-3.19.01/a2x/0000755000175000017500000000000012242431634012576 5ustar frankfrankbobcat-3.19.01/a2x/opis2.f0000644000175000017500000000012412223023055013767 0ustar frankfrankinline A2x &A2x::operator=(A2x const &other) { return operator=(other.str()); } bobcat-3.19.01/a2x/a2x0000644000175000017500000000171512223023055013210 0ustar frankfrank#ifndef INCLUDED_BOBCAT_A2X_ #define INCLUDED_BOBCAT_A2X_ #include #include namespace FBB { class A2x: public std::istringstream { static bool s_lastFail; public: A2x() = default; explicit A2x(char const *txt); // 1.f initialize from text explicit A2x(std::string const &str); // 2.f A2x(A2x const &other); // 3.f template operator Type(); // .f template Type to(); // .f A2x &operator=(char const *txt); A2x &operator=(std::string const &str); // 1.f A2x &operator=(A2x const &other); // 2.f static bool lastFail(); // .f }; #include "a2x1.f" #include "a2x2.f" #include "a2x3.f" #include "to.f" #include "optype.f" #include "opis1.f" #include "opis2.f" #include "lastfail.f" } // FBB #endif bobcat-3.19.01/a2x/opis1.f0000644000175000017500000000014612223023055013772 0ustar frankfrankinline A2x &A2x::operator=(std::string const &str) { return operator=(str.c_str()); } bobcat-3.19.01/a2x/lastfail.f0000644000175000017500000000006712223023055014540 0ustar frankfrankinline bool A2x::lastFail() { return s_lastFail; } bobcat-3.19.01/a2x/a2x3.f0000644000175000017500000000011312223023055013506 0ustar frankfrankinline A2x::A2x(A2x const &other) : std::istringstream(other.str()) {} bobcat-3.19.01/a2x/a2x2.f0000644000175000017500000000012112223023055013504 0ustar frankfrankinline A2x::A2x(std::string const &str) : std::istringstream(str.c_str()) {} bobcat-3.19.01/a2x/a2x.ih0000644000175000017500000000007212222576523013616 0ustar frankfrank#include "a2x" using namespace std; using namespace FBB; bobcat-3.19.01/a2x/a2x1.f0000644000175000017500000000015512223023055013512 0ustar frankfrankinline A2x::A2x(char const *txt) // initialize from text : std::istringstream(txt) {} bobcat-3.19.01/a2x/driver/0000755000175000017500000000000012222576523014076 5ustar frankfrankbobcat-3.19.01/a2x/driver/build0000755000175000017500000003553512222576523015136 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/driver // script generated by the C++ icmake script version 2.13 /* Configurable defines for the build script: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (default: defined). COMPILER: The compiler to use. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM #define COMPILER "g++" #define COPT "-Wall" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current; // contains name of current dir. int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", interactive, "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD CLASSES = "parser scanner "; if (exists("parser")) // subdir parser exists parser(); if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { printf("\n"); exec(COMPILER, "-o", exe, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef GRAMBUILD "-lfl", #endif #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); #ifdef GRAMBUILD libs += " -lfl"; #endif cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "driver.cc", // program source "driver", // static program library "driver" // binary program ); #else cpp_make ( "", "driver", // static- or so-library "" ); #endif } bobcat-3.19.01/a2x/driver/driver.cc0000644000175000017500000000122512222576523015700 0ustar frankfrank/* driver.cc */ #include #include "../a2x" using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { int x = A2x("12"); cout << x << endl; cout << x << endl; A2x a2x("12.50"); double d; d = a2x; cout << d << endl; A2x("12.345") >> d; cout << d << endl; cout << "Again: " << A2x("12.345").to() << endl; a2x = "err"; d = a2x; // d now 0 cout << d << endl; a2x = " a"; char c = a2x; // c now 'a' cout << c << endl; return 0; } /* Output: 12 12.5 12.345 0 a */ bobcat-3.19.01/a2x/data.cc0000644000175000017500000000006112222576523014020 0ustar frankfrank#include "a2x.ih" bool A2x::s_lastFail = false; bobcat-3.19.01/a2x/opis.cc0000644000175000017500000000047012222576523014065 0ustar frankfrank#include "a2x.ih" A2x &A2x::operator=(char const *txt) { clear(); // very important!!! If a previous conversion // failed, the object will remain useless // until executing this statement str(txt); return *this; } bobcat-3.19.01/a2x/to.f0000644000175000017500000000017412223023055013362 0ustar frankfranktemplate inline Type A2x::to() { Type t; return (s_lastFail = (*this >> t).fail()) ? Type() : t; } bobcat-3.19.01/a2x/optype.f0000644000175000017500000000012012223023055014247 0ustar frankfranktemplate inline A2x::operator Type() { return to(); } bobcat-3.19.01/align/0000755000175000017500000000000012242431634013176 5ustar frankfrankbobcat-3.19.01/align/opsizet.f0000644000175000017500000000007412223023055015034 0ustar frankfrankinline Align::operator size_t() const { return d_col; } bobcat-3.19.01/align/col.f0000644000175000017500000000006712223023055014116 0ustar frankfrankinline size_t Align::col() const { return d_col; } bobcat-3.19.01/align/row.f0000644000175000017500000000006712223023055014150 0ustar frankfrankinline size_t Align::row() const { return d_row; } bobcat-3.19.01/align/manip.f0000644000175000017500000000010012223023055014431 0ustar frankfrankinline Manipulator Align::manip() const { return d_manip; } bobcat-3.19.01/align/setmanip.f0000644000175000017500000000011012223023055015146 0ustar frankfrankinline void Align::setManip(Manipulator manip) { d_manip = manip; } bobcat-3.19.01/align/align.ih0000644000175000017500000000007412222576531014617 0ustar frankfrank#include "align" using namespace std; using namespace FBB; bobcat-3.19.01/align/align2.cc0000644000175000017500000000015212222576531014663 0ustar frankfrank#include "align.ih" Align::Align(Manipulator manip) : d_row(-1), d_col(0), d_manip(manip) {} bobcat-3.19.01/align/align0000644000175000017500000000206112223023055014203 0ustar frankfrank#ifndef INCLUDED_BOBCAT_ALIGN_ #define INCLUDED_BOBCAT_ALIGN_ #include namespace FBB { typedef std::ios_base &(*Manipulator)(std::ios_base &); #include "center.f" class Align { int d_row; // -1 or the row index to align size_t d_col; // acts as field width when setting the width of // an element. Manipulator d_manip; public: Align(int row, size_t column, Manipulator manip); Align(size_t col = 0, Manipulator manip = std::right); explicit Align(Manipulator manip); bool hasRow() const; operator size_t() const; // .f size_t col() const; // .f size_t row() const; // .f Manipulator manip() const; // .f void setWidth(size_t width); // .f void setManip(Manipulator manip); // .f }; #include "opsizet.f" #include "col.f" #include "row.f" #include "hasrow.f" #include "manip.f" #include "setmanip.f" #include "setwidth.f" } // FBB #endif bobcat-3.19.01/align/setwidth.f0000644000175000017500000000007712223023055015175 0ustar frankfrankinline void Align::setWidth(size_t size) { d_col = size; } bobcat-3.19.01/align/hasrow.f0000644000175000017500000000007612223023055014644 0ustar frankfrankinline bool Align::hasRow() const { return d_row != -1; } bobcat-3.19.01/align/center.f0000644000175000017500000000011312223023055014611 0ustar frankfrankinline std::ios_base ¢er(std::ios_base &stream) { return stream; } bobcat-3.19.01/align/align0.cc0000644000175000017500000000020312222576531014656 0ustar frankfrank#include "align.ih" Align::Align(int row, size_t col, Manipulator manip) : d_row(row), d_col(col), d_manip(manip) {} bobcat-3.19.01/align/align1.cc0000644000175000017500000000017112222576531014663 0ustar frankfrank#include "align.ih" Align::Align(size_t col, Manipulator manip) : d_row(-1), d_col(col), d_manip(manip) {} bobcat-3.19.01/arg/0000755000175000017500000000000012242431634012655 5ustar frankfrankbobcat-3.19.01/arg/noptions.f0000644000175000017500000000007612223023055014671 0ustar frankfrankinline size_t Arg__::nOptions() const { return d_nOptv; } bobcat-3.19.01/arg/instance.cc0000644000175000017500000000022512222576537015001 0ustar frankfrank#include "arg.ih" Arg &Arg::instance() { if (!s_arg) throw Exception() << "Arg::instance(): not yet initialized"; return *s_arg; } bobcat-3.19.01/arg/option1.f0000644000175000017500000000020012223023055014376 0ustar frankfrankinline size_t Arg::option(std::string *value, int optChar) const { return option(static_cast(0), value, optChar); } bobcat-3.19.01/arg/longoption2.cc0000644000175000017500000000023612222576537015451 0ustar frankfrank#include "arg.ih" LongOption__::LongOption__(char const *name, int optionChar) : d_name(name), d_type(AsCharOption), d_optionChar(optionChar) {} bobcat-3.19.01/arg/option5.cc0000644000175000017500000000122212222576537014570 0ustar frankfrank#include "arg.ih" size_t Arg__::option(size_t idx, string *value, char const *longOption) const { SSVMapIterator it = d_longOptv.find(longOption); if (it == d_longOptv.end()) return 0; size_t ret = it->second.size(); // size of the value-vector if (idx < ret && value) // if the idx is within range and *value = it->second[idx]; // value requested, return it. return ret; // return this option count. } size_t Arg::option(size_t idx, string *value, char const *longOption) const { return d_ptr->option(idx, value, longOption); } bobcat-3.19.01/arg/argpointers.cc0000644000175000017500000000033512222576537015534 0ustar frankfrank#include "arg.ih" char const **Arg__::argPointers() { if (!d_argPointer) d_argPointer = String::argv(d_argv); return d_argPointer; } char const **Arg::argPointers() { return d_ptr->argPointers(); } bobcat-3.19.01/arg/nlongoptions.cc0000644000175000017500000000013312222623204015704 0ustar frankfrank#include "arg.ih" size_t Arg::nLongOptions() const { return d_ptr->nLongOptions(); } bobcat-3.19.01/arg/basename.f0000644000175000017500000000011112223023055014561 0ustar frankfrankinline std::string const &Arg__::basename() const { return d_base; } bobcat-3.19.01/arg/plainlongoption.cc0000644000175000017500000000063012222576537016411 0ustar frankfrank#include "arg.ih" bool Arg__::plainLongOption(Arg__::LongOption const &longOption) { addLongOption(longOption.d_name); if (!longOption.d_optionChar) // it's a plain long option. return true; d_getOpt = longOption.d_optionChar; return false; // not a plain long option: // it's also a simple option. } bobcat-3.19.01/arg/arg2.cc0000644000175000017500000000375212222576537014040 0ustar frankfrank#include "arg.ih" Arg__::Arg__(char const *optstring, LongOption const * const begin, LongOption const * const end, int argc, char **argv) : d_argPointer(0), d_beyondDashes(find(argv, argv + argc, string("--")) - argv) { setBasename(argv[0]); string opts(*optstring == ':' ? "" : ":"); // ensure initial char is ':' opts += optstring; OptStructArray optStructs(end - begin + 1); // create array of n + 1 // structs for long options fillLongOptions(optStructs.get(), optstring, begin, end); opterr = 0; // prevent getopt() msgs to stderr int longOptionIndex; // receives the index of the long options while (true) { d_getOpt = getopt_long(argc, argv, opts.c_str(), optStructs.get(), &longOptionIndex); switch (d_getOpt) { case -1: d_beyondDashes += (d_beyondDashes != argc) - optind; copy(argv + optind, argv + argc, back_inserter(d_argv)); return; case ':': s_optChar[0] = optopt; d_msg = (optopt ? s_optChar : argv[optind - 1]); return; case '?': s_optChar[0] = optopt; d_msg = (optopt ? s_optChar : argv[optind - 1]); return; case 0: if (plainLongOption(begin[longOptionIndex])) break; // FALLING THROUGH IF LONG OPTION IS ALSO SHORT CHAR OPTION // in which case d_getOpt is set to the corresponding short // char option default: addCharOption(); break; } } } Arg::Arg(char const *optstring, LongOption const * const begin, LongOption const * const end, int argc, char **argv) : d_ptr(new Arg__(optstring, begin, end, argc, argv)) { d_ptr->verify(); } bobcat-3.19.01/arg/basename.cc0000644000175000017500000000014012222576537014744 0ustar frankfrank#include "arg.ih" std::string const &Arg::basename() const { return d_ptr->basename(); } bobcat-3.19.01/arg/nargs.cc0000644000175000017500000000011512222576537014305 0ustar frankfrank#include "arg.ih" size_t Arg::nArgs() const { return d_ptr->nArgs(); } bobcat-3.19.01/arg/initialize2.cc0000644000175000017500000000055512222576537015426 0ustar frankfrank#include "arg.ih" Arg &Arg::initialize(char const *optstring, LongOption const * const begin, LongOption const * const end, int argc, char **argv) { if (s_arg) throw Exception() << "Arg::initialize(): already initialized"; s_arg = new Arg(optstring, begin, end, argc, argv); return *s_arg; } bobcat-3.19.01/arg/initialize.cc0000644000175000017500000000036112222576537015337 0ustar frankfrank#include "arg.ih" Arg &Arg::initialize(char const *optstring, int argc, char **argv) { if (s_arg) throw Exception() << "Arg::initialize(): already initialized"; s_arg = new Arg(optstring, argc, argv); return *s_arg; } bobcat-3.19.01/arg/longoption0.cc0000644000175000017500000000020512222576537015443 0ustar frankfrank#include "arg.ih" LongOption__::LongOption__(char const *name) : d_name(name), d_type(None), d_optionChar(0) {} bobcat-3.19.01/arg/longoption1.cc0000644000175000017500000000022012222576537015441 0ustar frankfrank#include "arg.ih" LongOption__::LongOption__(char const *name, Type type) : d_name(name), d_type(type), d_optionChar(0) {} bobcat-3.19.01/arg/option3.cc0000644000175000017500000000111212222576537014564 0ustar frankfrank#include "arg.ih" size_t Arg__::option(size_t idx, string *value, int optChar) const { ISVMapIterator it = d_optv.find(optChar); if (it == d_optv.end()) return 0; size_t ret = it->second.size(); // size of the value-vector if (idx < ret && value) // if the idx is within range and *value = it->second[idx]; // value requested, return it. return ret; // return this option count. } size_t Arg::option(size_t idx, string *value, int optChar) const { return d_ptr->option(idx, value, optChar); } bobcat-3.19.01/arg/option6.cc0000644000175000017500000000057012222576537014576 0ustar frankfrank#include "arg.ih" size_t Arg__::option(size_t *idx, string *value, char const *longOpt) const { SSVMapIterator it = d_longOptv.find(longOpt); if (it == d_longOptv.end()) return 0; return firstNonEmpty(idx, value, it->second); } size_t Arg::option(size_t *idx, string *value, char const *longOpt) const { return d_ptr->option(idx, value, longOpt); } bobcat-3.19.01/arg/noptions.cc0000644000175000017500000000012312222576537015043 0ustar frankfrank#include "arg.ih" size_t Arg::nOptions() const { return d_ptr->nOptions(); } bobcat-3.19.01/arg/versionhelp.cc0000644000175000017500000000121512222576537015533 0ustar frankfrank#include "arg.ih" void Arg__::versionHelp(void (*usage)(string const &progname), char const *version, size_t minArgs, int helpFlag, int versionFlag) const { if (option(versionFlag) && !option(helpFlag)) { cout << basename() << " V" << version << '\n'; throw 1; } if (nArgs() < minArgs || option(helpFlag)) { usage(basename()); throw 1; } } void Arg::versionHelp(void (*usage)(string const &progname), char const *version, size_t minArgs, int helpFlag, int versionFlag) const { return d_ptr->versionHelp(usage, version, minArgs, helpFlag, versionFlag); } bobcat-3.19.01/arg/driver/0000755000175000017500000000000012222576537014162 5ustar frankfrankbobcat-3.19.01/arg/driver/getoptlong/0000755000175000017500000000000012222576537016344 5ustar frankfrankbobcat-3.19.01/arg/driver/getoptlong/build0000755000175000017500000003555312222576537017404 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/getoptlong // script generated by the C++ icmake script version 2.13 /* Configurable defines for the build script: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (default: defined). COMPILER: The compiler to use. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM #define COMPILER "g++" #define COPT "-Wall" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current; // contains name of current dir. int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", interactive, "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD CLASSES = "parser scanner "; if (exists("parser")) // subdir parser exists parser(); if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { printf("\n"); exec(COMPILER, "-o", exe, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef GRAMBUILD "-lfl", #endif #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); #ifdef GRAMBUILD libs += " -lfl"; #endif cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "getoptlong.cc", // program source "getoptlong", // static program library "getoptlong" // binary program ); #else cpp_make ( "", "getoptlong", // static- or so-library "" ); #endif } bobcat-3.19.01/arg/driver/getoptlong/getoptlong.h0000644000175000017500000000020012222576537020667 0ustar frankfrank#ifndef INCLUDED_GETOPTLONG_H_ #define INCLUDED_GETOPTLONG_H_ #include #include namespace FBB { } #endif bobcat-3.19.01/arg/driver/getoptlong/getoptlong.ih0000644000175000017500000000015212222576537021046 0ustar frankfrank#include "getoptlong.h" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/arg/driver/getoptlong/getoptlong.cc0000644000175000017500000000223312222576537021035 0ustar frankfrank#include "getoptlong.h" #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { int value; opterr = 0; struct option longopts [] = { {"a-opt", 0, 0, 'a'}, {"one", 0, &value, 100}, {"two", 0, &value, 200}, {0, } }; while (true) { int c = getopt_long(argc, argv, "abc", longopts, 0); char ch = c; char co = optopt; switch (c) { case EOF: cout << "All processed\n"; return 0; case ':': cout << "ArgData::ArgData(): missing option value" << endl; break; case '?': cout << "ArgData::ArgData(): unknown option" << optopt << " (" << co << ")" << endl; break; case 0: cout << "0 return. val = " << value << endl; break; default: cout << "Default return. c = " << ch << ", optopt = " << optopt << endl; break; } } } bobcat-3.19.01/arg/driver/build0000755000175000017500000000104712222576537015211 0ustar frankfrank#!/bin/bash ln -sf ../arg . ln -sf ../arg.ih . tput clear case $1 in (b) rm arg arg.ih g++ -DBOBCAT --static --std=c++0x -I../../tmp -o driver driver.cc \ -L../../tmp/lib -lbobcat -s ;; (o) g++ --std=c++0x -o driver *.cc ../tmp/o/*.o -lbobcat # -s ;; (c) g++ --std=c++0x -o driver *.cc -lbobcat -s ;; (*) echo $0 b links to bobcat built by 'build libraries all' echo $0 o links to the files in ../tmp/o echo $0 c links to the files in the current dir only ;; esac bobcat-3.19.01/arg/driver/driver.ih0000644000175000017500000000014612222576537016000 0ustar frankfrank#include "driver.h" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/arg/driver/driver.cc0000644000175000017500000000644212222576537015772 0ustar frankfrank/* driver.cc */ #include #include #include #include #ifdef BOBCAT #include #else #include "arg" #endif using namespace std; using namespace FBB; void optcheck(char c) { Arg &arg = Arg::instance(); if (size_t count = arg.option(c)) cout << "Saw option " << c << " " << count << " times" << '\n'; if (string("def").find(c) != string::npos) { string value; size_t idx; idx = arg.option(&value, c); cout << idx << " returned by option() for " "option " << c << ", which has value `" << value << "'\n"; size_t count = arg.option(&idx, &value, c); cout << count << " times option " << c << '\n'; if (idx == count) cout << "No non-empty option values" << '\n'; else { cout << "First non-empty option at " << idx << '\n'; for (size_t ix = 0; ix < count; ++ix) { arg.option(ix, &value, c); cout << ix << ": " << value << '\n'; } } } cout << '\n'; } void longopt(char const *longOpt) { string value; Arg &arg = Arg::instance(); size_t opt = arg.option(&value, longOpt); if (!opt) return; cout << longOpt << " " << opt << " times:\t" << (value.length() ? value : "-- no arg--") << '\n'; } void usage(string const &progname) { cout << "Usage: " << progname << " arg options\n" "where:\n" " arg: any argument\n" " options: any option from abcd:e:f:hv\n" " try options requiring arguments without specifying an " "argument\n" " try other options too. -h provides this help,\n" " -v provides the version\n" "Available long options:\n" " --optional, --extra (+ arg), --file (as -f),\n" " --version (as -v), --add (as -a)\n"; } namespace { } int main(int argc, char **argv) try { Arg::LongOption lo[] = { {"optional", Arg::Optional}, {"extra", Arg::Required}, {"file", 'f'}, {"version", 'v'}, {"add", 'a'} }; try { Arg::initialize("abcd:e:f:hv", lo, lo + 5, argc, argv); Arg &arg = Arg::instance(); arg.versionHelp(usage, "0.00", 1); for_each("abcdefg", "abcdefg" + 7, optcheck) ; for (size_t idx = 0; idx < arg.nArgs(); idx++) cout << "Argument " << idx << " = " << arg[idx] << '\n'; cout << '\n'; cout << "Long options:\n" << dec; longopt("optional"); longopt("extra"); longopt("file"); longopt("add"); } catch (Errno const &e) { cout << e.which() << " " << e.why() << '\n'; } } catch (int x) { cout << "int exception caught, value = " << x << '\n'; return x; } catch (Errno const &e) { cout << "Errno exception caught, why() = " << e.why() << "\n" "which() is: " << e.which() << '\n'; return e.which(); } catch (...) { cout << "Unexpected exception caught, shouldn't happen\n"; return 1; } bobcat-3.19.01/arg/beyonddashes.cc0000644000175000017500000000013012222576537015640 0ustar frankfrank#include "arg.ih" int Arg::beyondDashes() const { return d_ptr->beyondDashes(); } bobcat-3.19.01/arg/data.cc0000644000175000017500000000015112222576537014104 0ustar frankfrank#include "arg.ih" Arg *Arg::s_arg; string Arg__::s_dirsep("/"); char Arg__::s_optChar[] = " "; bobcat-3.19.01/arg/option2.cc0000644000175000017500000000045512222576537014574 0ustar frankfrank#include "arg.ih" size_t Arg__::option(std::string const &optchars) const { size_t count = 0; for (char const *cp = optchars.c_str(); *cp; ++cp) count += option(*cp); return count; } size_t Arg::option(std::string const &optchars) const { return d_ptr->option(optchars); } bobcat-3.19.01/arg/setbasename.cc0000644000175000017500000000027212222576537015466 0ustar frankfrank#include "arg.ih" void Arg__::setBasename(string const &argv0) { string::size_type idx = argv0.rfind(s_dirsep); d_base = idx == string::npos ? argv0 : argv0.substr(idx + 1); } bobcat-3.19.01/arg/option4.cc0000644000175000017500000000054112222623204014552 0ustar frankfrank#include "arg.ih" size_t Arg__::option(size_t *idx, string *value, int optChar) const { ISVMapIterator it = d_optv.find(optChar); if (it == d_optv.end()) return 0; return firstNonEmpty(idx, value, it->second); } size_t Arg::option(size_t *idx, string *value, int optChar) const { return d_ptr->option(idx, value, optChar); } bobcat-3.19.01/arg/verify.cc0000644000175000017500000000051512222576537014503 0ustar frankfrank#include "arg.ih" void Arg__::verify() { switch (d_getOpt) { case ':': throw Exception(1) << "ArgData::ArgData(): missing value for option: " << d_msg; case '?': throw Exception(1) << "ArgData::ArgData(): unknown option: " << d_msg; default: return; } } bobcat-3.19.01/arg/filllongoptions.cc0000644000175000017500000000056012222576537016421 0ustar frankfrank#include "arg.ih" void Arg__::fillLongOptions(OptStruct *optStruct, std::string const &optString, LongOption const * const begin, LongOption const * const end) { for (LongOption const *it = begin; it != end; ++it, ++optStruct) addLongOption(optStruct, optString, *it); } bobcat-3.19.01/arg/operatorindex.cc0000644000175000017500000000014012222576537016054 0ustar frankfrank#include "arg.ih" char const *Arg::operator[](size_t idx) const { return (*d_ptr)[idx]; } bobcat-3.19.01/arg/getname.f0000644000175000017500000000011712223023055014434 0ustar frankfrankinline std::string const &LongOption__::getName() const { return d_name; } bobcat-3.19.01/arg/option2.f0000644000175000017500000000021612223023055014406 0ustar frankfrankinline size_t Arg::option(std::string *value, char const *longOption) const { return option(static_cast(0), value, longOption); } bobcat-3.19.01/arg/optionchar.f0000644000175000017500000000011112223023055015154 0ustar frankfrankinline int LongOption__::optionChar() const { return d_optionChar; } bobcat-3.19.01/arg/beyonddashes.f0000644000175000017500000000010612223023055015462 0ustar frankfrankinline int Arg__::beyondDashes() const { return d_beyondDashes; } bobcat-3.19.01/arg/addlongoption2.cc0000644000175000017500000000132412222576537016121 0ustar frankfrank#include "arg.ih" /* called by fillLongOption() to create the array of `struct option' (OptStruct) elements to be interpreted by getopt_long() */ void Arg__::addLongOption(OptStruct *optStruct, string const &optString, LongOption const &longOption) { static int notUsed; optStruct->name = longOption.d_name.c_str(); if (longOption.d_optionChar) // existing option { optStruct->has_arg = setOptionType(optString, longOption); optStruct->flag = 0; optStruct->val = longOption.d_optionChar; } else { optStruct->has_arg = longOption.d_type, optStruct->flag = ¬Used; } } bobcat-3.19.01/arg/arg0000644000175000017500000000676112223023055013354 0ustar frankfrank#ifndef INCLUDED_BOBCAT_ARG_ #define INCLUDED_BOBCAT_ARG_ /* Singleton Class built around getopt() and getopt_long() (3) */ #include #include #include namespace FBB { class ArgTypes__ { protected: typedef struct option OptStruct; typedef std::vector StringVector; public: enum Type { None = 0, Required = 1, Optional = 2, AsCharOption, }; }; class LongOption__: public ArgTypes__ { friend class Arg__; friend class ArgConfig; std::string d_name; Type d_type; int d_optionChar; public: explicit LongOption__(char const *name); LongOption__(char const *name, Type type); LongOption__(char const *name, int optionChar); std::string const &getName() const; // .f int optionChar() const; // .f }; class Arg__; class Arg: public ArgTypes__ { friend class ArgConfig; // accesses the constructors and // longOption() Arg__ *d_ptr; // pointer to the implementation static Arg *s_arg; // points to Singleton Arg public: typedef FBB::LongOption__ LongOption; static Arg &initialize(char const *optstring, int argc, char **argv); static Arg &initialize(char const *optstring, LongOption const * const begin, LongOption const * const end, int argc, char **argv); static Arg &instance(); int beyondDashes() const; std::string const &basename() const; size_t nArgs() const; // total number of specified short (and combined long) options size_t nOptions() const; // total numer of long-only options specified size_t nLongOptions() const; size_t option(int option) const; // 1 size_t option(std::string const &optchars) const; // 2 size_t option(size_t idx, std::string *value, int option) const; // 3 size_t option(size_t *idx, std::string *value, int option) const; // 4 size_t option(size_t idx, std::string *value, char const *longOption) const; // 5 size_t option(size_t *idx, std::string *value, char const *longOption) const; // 6 size_t option(std::string *value, int optChar) const; // 1.f // 2.f size_t option(std::string *value, char const *longOption) const; char const *operator[](size_t idx) const; void versionHelp(void (*usage)(std::string const &progname), char const *version, size_t minArgs, int helpFlag = 'h', int versionFlag = 'v') const; char const **argPointers(); private: Arg(Arg const &other) = delete; Arg &operator=(Arg const &other) = delete; Arg(char const *optstring, int argc, char **argv); // 1 Arg(char const *optstring, // 2 LongOption const * const begin, LongOption const * const end, int argc, char **argv); }; #include "getname.f" #include "optionchar.f" #include "option1.f" #include "option2.f" } // FBB #endif bobcat-3.19.01/arg/option1.cc0000644000175000017500000000036212222576537014570 0ustar frankfrank#include "arg.ih" size_t Arg__::option(int optChar) const { ISVMapIterator it = d_optv.find(optChar); return it == d_optv.end() ? 0 : it->second.size(); } size_t Arg::option(int optChar) const { return d_ptr->option(optChar); } bobcat-3.19.01/arg/addcharoption.cc0000644000175000017500000000017012222576537016013 0ustar frankfrank#include "arg.ih" void Arg__::addCharOption() { d_optv[d_getOpt].push_back(optarg ? optarg : ""); ++d_nOptv; } bobcat-3.19.01/arg/arg.ih0000644000175000017500000001216312223023055013744 0ustar frankfrank#include "arg" #include #include #include #include #include #include #include #include namespace FBB { class Arg__: public ArgTypes__ { friend class Arg; typedef FBB::LongOption__ LongOption; typedef struct option OptStruct; typedef std::vector StringVector; typedef std::unordered_map IntStringVectorMap; typedef IntStringVectorMap::const_iterator ISVMapIterator; typedef std::unordered_map StringStringVectorMap; typedef StringStringVectorMap::const_iterator SSVMapIterator; std::string d_base; char const **d_argPointer; std::vector d_argv; // remaining arguments // after removing the // options IntStringVectorMap d_optv; // short (and associated // long options). // 1st value: option char; // 2nd value: optionvalue // or empty string. size_t d_nOptv; // count of ALL of the // previous options StringStringVectorMap d_longOptv; // specified long options size_t d_nLongOptions; // count of ALL of the // following options char const *d_msg; // info about erroneous opt. int d_getOpt; // value returned by getopt() int d_beyondDashes; // idx of 1st arg beyond -- static std::string s_dirsep; static char s_optChar[]; // used by the constructors public: int beyondDashes() const; // .i std::string const &basename() const; // .i size_t nArgs() const; // .i // total number of specified short (and combined long) options size_t nOptions() const; // .i // total numer of long-only options specified size_t nLongOptions() const; // .i size_t option(int option) const; // 1 size_t option(std::string const &optchars) const; // 2 size_t option(size_t idx, std::string *value, int option) const; // 3 size_t option(std::string *value, int optChar) const; size_t option(size_t *idx, std::string *value, int option) const; // 4 size_t option(size_t idx, std::string *value, char const *longOption) const; // 5 //size_t option(std::string *value, char const *longOption) const; size_t option(size_t *idx, std::string *value, char const *longOption) const; // 6 char const *operator[](size_t idx) const; void versionHelp(void (*usage)(std::string const &progname), char const *version, size_t minArgs, int helpFlag = 'h', int versionFlag = 'v') const; char const **argPointers(); private: Arg__(Arg__ const &other) = delete; Arg__ &operator=(Arg const &other) = delete; friend class ArgConfig; // accesses the constructors and // longOption() // 1 Arg__(char const *optstring, int argc, char **argv); Arg__(char const *optstring, // 2 LongOption const * const begin, LongOption const * const end, int argc, char **argv); void addCharOption(); // in d_getOpt void addLongOption(std::string const &longName); // 1 void addLongOption(OptStruct *optStructs, // 2 std::string const &optString, LongOption const &longOption); void verify(); size_t firstNonEmpty(size_t *idx, std::string *value, StringVector const &sv) const; void setBasename(std::string const &argv0); void fillLongOptions( OptStruct *optStructs, std::string const &optString, LongOption const * const begin, LongOption const * const end); bool plainLongOption(LongOption const &longOption); int setOptionType(std::string const &optString, LongOption const &longOption); }; #include "beyonddashes.f" #include "basename.f" #include "nargs.f" #include "nlongoptions.f" #include "noptions.f" #include "opindex.f" } // FBB using namespace FBB; using namespace std; bobcat-3.19.01/arg/setoptiontype.cc0000644000175000017500000000103212222576537016120 0ustar frankfrank#include "arg.ih" int Arg__::setOptionType(string const &optString, LongOption const &longOption) { string::size_type pos = optString.find_first_of(longOption.d_optionChar); if (pos == string::npos) throw Exception(EINVAL) << "Arg__::setOptionType()" << ": short option `" << static_cast(longOption.d_optionChar) << "' not found"; return optString[pos + 1] == ':' ? Required : None; } bobcat-3.19.01/arg/opindex.f0000644000175000017500000000016212223023055014462 0ustar frankfrankinline char const *Arg__::operator[](size_t idx) const { return (idx >= nArgs()) ? 0 : d_argv[idx].c_str(); } bobcat-3.19.01/arg/arg1.cc0000644000175000017500000000224012222576537014026 0ustar frankfrank#include "arg.ih" Arg__::Arg__(char const *optstring, int argc, char **argv) : d_argPointer(0), d_beyondDashes(find(argv, argv + argc, string("--")) - argv) { setBasename(argv[0]); string opts(*optstring == ':' ? "" : ":"); // ensure initial char is ':' opts += optstring; opterr = 0; // prevent getopt() msgs to stderr while (true) { d_getOpt = getopt(argc, argv, opts.c_str()); switch (d_getOpt) { case -1: d_beyondDashes += (d_beyondDashes != argc) - optind; copy(argv + optind, argv + argc, back_inserter(d_argv)); return; case ':': s_optChar[0] = optopt; d_msg = (optopt ? s_optChar : argv[optind - 1]); return; case '?': s_optChar[0] = optopt; d_msg = (optopt ? s_optChar : argv[optind - 1]); return; default: addCharOption(); break; } } } Arg::Arg(char const *optstring, int argc, char **argv) : d_ptr(new Arg__(optstring, argc, argv)) { d_ptr->verify(); } bobcat-3.19.01/arg/nargs.f0000644000175000017500000000010112223023055014117 0ustar frankfrankinline size_t Arg__::nArgs() const { return d_argv.size(); } bobcat-3.19.01/arg/nlongoptions.f0000644000175000017500000000010212223023055015537 0ustar frankfrankinline size_t Arg__::nLongOptions() const { return d_nOptv; } bobcat-3.19.01/arg/firstnonempty.cc0000644000175000017500000000073212222576537016121 0ustar frankfrank#include "arg.ih" size_t Arg__::firstNonEmpty(size_t *idx, string *value, StringVector const &sv) const { StringVector::const_iterator sit = find_if(sv.begin(), sv.end(), bind2nd(not_equal_to(), "")); if (sit == sv.end()) *idx = sv.size(); else { *idx = sit - sv.begin(); if (value != 0) *value = *sit; } return sv.size(); } bobcat-3.19.01/arg/addlongoption1.cc0000644000175000017500000000023112222576537016114 0ustar frankfrank#include "arg.ih" void Arg__::addLongOption(string const &longName) { d_longOptv[longName].push_back(optarg ? optarg : ""); ++d_nLongOptions; } bobcat-3.19.01/argconfig/0000755000175000017500000000000012242431634014043 5ustar frankfrankbobcat-3.19.01/argconfig/argconfig3.cc0000644000175000017500000000053012222576524016400 0ustar frankfrank#include "argconfig.ih" ArgConfig::ArgConfig(char const *optstring, LongOption const *begin, LongOption const *const end, int argc, char **argv, Comment cType, SearchCasing sType, Indices iType) : Arg(optstring, begin, end, argc, argv), ConfigFile(cType, sType, iType), d_ptr(new ArgConfig__(begin, end)) // 5 {} bobcat-3.19.01/argconfig/line.f0000644000175000017500000000015012223023055015126 0ustar frankfrankinline std::string const &ArgConfig::line(size_t idx) const { return ConfigFile::operator[](idx); } bobcat-3.19.01/argconfig/findlongoption.cc0000644000175000017500000000101012222576524017401 0ustar frankfrank#include "argconfig.ih" // return ConfigFile's RE_iterator to the configfile's long option ArgConfig::RE_iteratorPair ArgConfig::findLongOption(int optChar) { // find the long option given the short option char auto optIt = d_ptr->find(optChar); return optIt == d_ptr->findEnd() ? // not found, beginEndRE() : // else return an iter to the longConfigOpt(optIt->second); // option's line. } bobcat-3.19.01/argconfig/argconfig0000644000175000017500000001026212223023055015717 0ustar frankfrank#ifndef INCLUDED_BOBCAT_ARGCONFIG_ #define INCLUDED_BOBCAT_ARGCONFIG_ #include #include #include #include namespace FBB { class ArgConfig__; class ArgConfig: public Arg, public ConfigFile { static ArgConfig *s_argconfig; // points to Singleton ArgConfig ArgConfig__ *d_ptr; public: static ArgConfig &initialize(char const *optstring, // 1 int argc, char **argv, Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); static ArgConfig &initialize(char const *optstring, // 2 int argc, char **argv, std::string const &fname, Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); static ArgConfig &initialize(char const *optstring, // 3 LongOption const *const begin, LongOption const *const end, int argc, char **argv, Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); static ArgConfig &initialize(char const *optstring, // 4 LongOption const *const begin, LongOption const *const end, int argc, char **argv, std::string const &fname, Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); static ArgConfig &instance(); size_t option(int option); // 1 size_t option(std::string const &optchars); // 2 size_t option(std::string *value, int optChar); // 3 size_t option(std::string *value, char const *longOption); // 4 size_t option(size_t idx, // 1.f std::string *value, int option) const; size_t option(size_t *idx, // 2.f std::string *value, int option) const; size_t option(size_t idx, std::string *value, // 3.f char const *longOption) const; size_t option(size_t *idx, std::string *value, // 4.f char const *longOption) const; char const *operator[](size_t idx) const; // Arg's [] .f std::string const &line(size_t idx) const; // ConfigFile's [] .f private: ArgConfig(ArgConfig const &other) = delete; ArgConfig &operator=(ArgConfig const &other) = delete; ArgConfig(char const *optstring, // 1 int argc, char **argv, Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); ArgConfig(char const *optstring, // 2 int argc, char **argv, std::string const &fname, Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); ArgConfig(char const *optstring, // 3 LongOption const *begin, LongOption const *const end, int argc, char **argv, Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); ArgConfig(char const *optstring, // 4 LongOption const *begin, LongOption const *const end, int argc, char **argv, std::string const &fname, Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); RE_iteratorPair findLongOption(int optChar); RE_iteratorPair longConfigOpt(std::string const &longOpt); }; #include "option1.f" #include "option2.f" #include "option3.f" #include "option4.f" #include "opindex.f" #include "line.f" } // FBB #endif bobcat-3.19.01/argconfig/argconfig2.cc0000644000175000017500000000040312222576524016376 0ustar frankfrank#include "argconfig.ih" ArgConfig::ArgConfig(char const *optstring, int argc, char **argv, std::string const &fname, Comment cType, SearchCasing sType, Indices iType) : Arg(optstring, argc, argv), ConfigFile(fname, cType, sType, iType) {} bobcat-3.19.01/argconfig/instance.cc0000644000175000017500000000027112222576524016164 0ustar frankfrank#include "argconfig.ih" ArgConfig &ArgConfig::instance() { if (!s_argconfig) throw Exception() << "ArgConfig::instance(): not yet initialized"; return *s_argconfig; } bobcat-3.19.01/argconfig/option1.f0000644000175000017500000000027112223023055015574 0ustar frankfrankinline size_t ArgConfig::option(size_t idx, std::string *value, int optChar) const { return Arg::option(idx, value, optChar); } bobcat-3.19.01/argconfig/find.f0000644000175000017500000000022112223023055015116 0ustar frankfrankinline std::unordered_map::const_iterator ArgConfig__::find(int optChar) const { return d_longOption.find(optChar); } bobcat-3.19.01/argconfig/option3.f0000644000175000017500000000027712223023055015604 0ustar frankfrankinline size_t ArgConfig::option(size_t idx, std::string *value, char const *longOption) const { return Arg::option(idx, value, longOption); } bobcat-3.19.01/argconfig/initialize2.cc0000644000175000017500000000065512222576524016611 0ustar frankfrank#include "argconfig.ih" ArgConfig &ArgConfig::initialize(char const *optstring, int argc, char **argv, string const &fname, Comment cType, SearchCasing sType, Indices iType) { if (s_argconfig) throw Exception() << "ArgConfig::initialize(): already initialized"; s_argconfig = new ArgConfig(optstring, argc, argv, fname, cType, sType, iType); return *s_argconfig; } bobcat-3.19.01/argconfig/option4.f0000644000175000017500000000027212223023055015600 0ustar frankfrankinline size_t ArgConfig::option(size_t *idx, std::string *value, char const *longOpt) const { return Arg::option(idx, value, longOpt); } bobcat-3.19.01/argconfig/option3.cc0000644000175000017500000000105712222576524015756 0ustar frankfrank#include "argconfig.ih" // same as Arg::option's equivalent size_t ArgConfig::option(string *value, int optChar) { static size_t const zero = 0; // prevents amd64 ambiguities where size_t ret = Arg::option(zero, value, optChar); // (size_t)0 != 0U if (ret != 0) return ret; auto iterators = findLongOption(optChar); if (iterators.second == iterators.first) return 0; if (value) *value = findKeyTail(d_ptr->find(optChar)->second + ":?", 1); return iterators.second - iterators.first; } bobcat-3.19.01/argconfig/initialize1.cc0000644000175000017500000000056212222576524016605 0ustar frankfrank#include "argconfig.ih" ArgConfig &ArgConfig::initialize(char const *optstring, int argc, char **argv, Comment cType, SearchCasing sType, Indices iType) { if (s_argconfig) throw Exception() << "ArgConfig::initialize(): already initialized"; s_argconfig = new ArgConfig(optstring, argc, argv, cType, sType, iType); return *s_argconfig; } bobcat-3.19.01/argconfig/findend.f0000644000175000017500000000020112223023055015603 0ustar frankfrankinline std::unordered_map::const_iterator ArgConfig__::findEnd() const { return d_longOption.end(); } bobcat-3.19.01/argconfig/driver/0000755000175000017500000000000012222576524015344 5ustar frankfrankbobcat-3.19.01/argconfig/driver/driver.rc0000644000175000017500000000051712222576524017170 0ustar frankfrank# This is the configuration file used with the ArgConfig driver program # This will result in a count of 3 of the check for -o: option anything in between is ok option 12 # Options may have values associated with them. The 'value-option' should # produce such a value: value-option this is a value specified with `value-option' bobcat-3.19.01/argconfig/driver/build0000755000175000017500000000123512222576524016372 0ustar frankfrank#!/bin/bash ln -sf ../argconfig . ln -sf ../argconfig.ih . case $1 in (b) g++ --std=c++0x -o driver *.cc -lbobcat -s ;; (o) g++ --std=c++0x -o driver *.cc -L../../tmp -largconfig -lbobcat -s ;; (l) g++ --std=c++0x --static -I../../tmp -o driver *.cc \ -L../../tmp/lib -lbobcat -s ;; (c) g++ --std=c++0x -o driver *.cc -lbobcat -s ;; (*) echo $0 b links to the installed bobcat library echo $0 c links to the files in the current dir only echo $0 l links to the library in ../../tmp/lib echo $0 o links to the files in ../../tmp/o ;; esac bobcat-3.19.01/argconfig/driver/driver.ih0000644000175000017500000000014612222576524017162 0ustar frankfrank#include "driver.h" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/argconfig/driver/driver.cc0000644000175000017500000000355112222576524017152 0ustar frankfrank#include #include #include "argconfig" #include using namespace std; using namespace FBB; namespace { ArgConfig::LongOption lo[] = { ArgConfig::LongOption("option", 'o'), ArgConfig::LongOption("option-value", 'v') }; } class X { ArgConfig &d_arg; public: X(); void function(); }; X::X() : d_arg(ArgConfig::instance()) {} void X::function() { if (d_arg.nArgs() == 0) throw Errno("Provide the name of a config file as 1st arg"); cout << "Counting " << d_arg.option('o') << " instances of -o or " "--option\n"; cerr << "\n" "Now opening config file `" << d_arg[0] << "'\n"; d_arg.open(d_arg[0]); // Now open the config file explicitly // (alternatively: use a constructor expecting // a file name) cout << "\n" "ALL LINES IN THE CONFIG FILE:\n"; copy(d_arg.begin(), d_arg.end(), ostream_iterator(cout, "\n")); cout << "\n" "Counting " << d_arg.option('o') << " instances of -o or " "--option\n"; string optval; size_t count = d_arg.option(&optval, 'v'); cout << "\n" "Counting " << count << " instances of -v or --option-value\n" "The first one having value `" << optval << "'\n"; } int main(int argc, char **argv) try { ArgConfig &arg = ArgConfig::initialize("cov:", lo, lo + 2, argc, argv); if (arg.option('c')) { cout << "Comment lines are removed from the config file\n\n"; arg.setCommentHandling(ArgConfig::RemoveComment); } X x; x.function(); } catch (Errno const &err) { cout << "Terminating " << err.why() << endl; return 1; } bobcat-3.19.01/argconfig/driver/config0000644000175000017500000000040112222576524016527 0ustar frankfrank# these options are also defined by driver.cc option option-value: \#x\\yz \\ option-value: #xyz this line \ continues over \ multiple lines # other lines may also be provided, lines starting with # are comment a line not containing an option bobcat-3.19.01/argconfig/initialize4.cc0000644000175000017500000000076512222576524016615 0ustar frankfrank#include "argconfig.ih" ArgConfig &ArgConfig::initialize(char const *optstring, LongOption const *const begin, LongOption const *const end, int argc, char **argv, string const &fname, Comment cType, SearchCasing sType, Indices iType) { if (s_argconfig) throw Exception() << "ArgConfig::initialize(): already initialized"; s_argconfig = new ArgConfig(optstring, begin, end, argc, argv, fname, cType, sType, iType); return *s_argconfig; } bobcat-3.19.01/argconfig/data.cc0000644000175000017500000000007412222576524015272 0ustar frankfrank#include "argconfig.ih" ArgConfig *ArgConfig::s_argconfig; bobcat-3.19.01/argconfig/argconfig.ih0000644000175000017500000000155512223023055016323 0ustar frankfrank#include "argconfig" #include #include #include #include #include #include namespace FBB { class ArgConfig__ { // find long options given short // option char std::unordered_map d_longOption; public: ArgConfig__(LongOption__ const *begin, LongOption__ const *const end); std::unordered_map::const_iterator find(int optChar) const; // .i std::unordered_map::const_iterator findEnd() const; // .i }; #include "find.f" #include "findend.f" } // FBB using namespace FBB; using namespace std; bobcat-3.19.01/argconfig/argconfig5.cc0000644000175000017500000000037612222576524016412 0ustar frankfrank#include "argconfig.ih" ArgConfig__::ArgConfig__(LongOption__ const *begin, LongOption__ const *const end) { while (begin != end) { d_longOption[begin->optionChar()] = begin->getName(); ++begin; } } bobcat-3.19.01/argconfig/option2.cc0000644000175000017500000000035512222576524015755 0ustar frankfrank#include "argconfig.ih" size_t ArgConfig::option(std::string const &optchars) { size_t count = 0; char const *cp = optchars.c_str(); while (*cp) { count += option(*cp); ++cp; } return count; } bobcat-3.19.01/argconfig/option4.cc0000644000175000017500000000055612222624233015751 0ustar frankfrank#include "argconfig.ih" size_t ArgConfig::option(string *value, char const *longOption) { size_t ret = Arg::option(value, longOption); if (ret != 0) return ret; auto iterators = longConfigOpt(longOption); ret = iterators.second - iterators.first; if (value && ret != 0) *value = findKeyTail(longOption, 1); return ret; } bobcat-3.19.01/argconfig/option2.f0000644000175000017500000000027212223023055015576 0ustar frankfrankinline size_t ArgConfig::option(size_t *idx, std::string *value, int optChar) const { return Arg::option(idx, value, optChar); } bobcat-3.19.01/argconfig/argconfig4.cc0000644000175000017500000000057712222576524016414 0ustar frankfrank#include "argconfig.ih" ArgConfig::ArgConfig(char const *optstring, LongOption const *begin, LongOption const *const end, int argc, char **argv, string const &fname, Comment cType, SearchCasing sType, Indices iType) : Arg(optstring, begin, end, argc, argv), ConfigFile(fname, cType, sType, iType), d_ptr(new ArgConfig__(begin, end)) // 5 {} bobcat-3.19.01/argconfig/argconfig1.cc0000644000175000017500000000034212222576524016377 0ustar frankfrank#include "argconfig.ih" ArgConfig::ArgConfig(char const *optstring, int argc, char **argv, Comment cType, SearchCasing sType, Indices iType) : Arg(optstring, argc, argv), ConfigFile(cType, sType, iType) {} bobcat-3.19.01/argconfig/longconfigopt.cc0000644000175000017500000000027712222576524017236 0ustar frankfrank#include "argconfig.ih" ArgConfig::RE_iteratorPair ArgConfig::longConfigOpt(string const &longOpt) { string pattern = "^\\s*" + longOpt + ":?(\\s|$)"; return beginEndRE(pattern); } bobcat-3.19.01/argconfig/option1.cc0000644000175000017500000000027212222576524015752 0ustar frankfrank#include "argconfig.ih" size_t ArgConfig::option(int optChar) { auto iterators = findLongOption(optChar); return Arg::option(optChar) + (iterators.second - iterators.first); } bobcat-3.19.01/argconfig/opindex.f0000644000175000017500000000014012223023055015644 0ustar frankfrankinline char const *ArgConfig::operator[](size_t idx) const { return Arg::operator[](idx); } bobcat-3.19.01/argconfig/initialize3.cc0000644000175000017500000000073212222576524016606 0ustar frankfrank#include "argconfig.ih" ArgConfig &ArgConfig::initialize(char const *optstring, LongOption const *const begin, LongOption const *const end, int argc, char **argv, Comment cType, SearchCasing sType, Indices iType) { if (s_argconfig) throw Exception() << "ArgConfig::initialize(): already initialized"; s_argconfig = new ArgConfig(optstring, begin, end, argc, argv, cType, sType, iType); return *s_argconfig; } bobcat-3.19.01/autoptr/0000755000175000017500000000000012222576536013613 5ustar frankfrankbobcat-3.19.01/autoptr/driver/0000755000175000017500000000000012222576536015106 5ustar frankfrankbobcat-3.19.01/autoptr/driver/build0000755000175000017500000000005612222576536016134 0ustar frankfrank#!/bin/sh g++ -o autoptr autoptr.cc -lbobcat bobcat-3.19.01/autoptr/driver/autoptr.cc0000644000175000017500000000261112222576536017113 0ustar frankfrank#include "../autoptr" using namespace std; using namespace FBB; int main() { AutoPtr autoInt(new int(4)); cout << "\n1: test simple construction and copy construction\n\n"; { AutoPtr auto2(autoInt); cout << *auto2 << endl; cout << *((0 + auto2) - 2) << endl; } cout << *autoInt << endl; cout << "\n2: test array\n\n"; { AutoPtr autoarr(new int[5], 5); autoarr[1] = 1; autoarr[2] = 2; cout << autoarr[2] << endl; cout << autoarr[3] << endl; cout << "\n3: assign to former autoPtr of different data size\n\n"; autoInt = autoarr; } cout << autoInt[2] << endl; cout << autoInt[3] << endl; cout << "\n4: pointer-based operations\n\n"; cout << *((autoInt + 4) - 2) << endl; cout << *((autoInt + 6) - 4) << endl; cout << ((6 + autoInt) - 4)[0] << endl; cout << "\n5: resetting\n\n"; AutoPtr autoSave(autoInt); autoInt.reset(new int(12345)); cout << *autoInt << endl; cout << autoSave[2] << endl; cout << "\n6: resetting all\n\n"; autoSave = autoInt; autoInt.resetAll(new int(12345)); cout << *autoInt << endl; cout << *autoSave << endl; } bobcat-3.19.01/autoptr/autoptr0000644000175000017500000001632212222576536015240 0ustar frankfrank#include #include namespace FBB { template class AutoPtr { class RefData: public RefCount { Data *d_data; size_t d_size; // 0: single pointer, otherwise array public: RefData(); RefData(Data *d_data, size_t size); RefData(RefData const &other) = delete; virtual ~RefData(); Data *get(int idx); Data *releaseOne(); // Return one allocated // copy, lose share count Data *releaseAll(); // Return allocated data // lose all shares void reset(Data *data, size_t size = 0);// reset to data[size] // or data if size == 0 private: virtual RefCount *clone() const; void destroy(); }; RefData *d_data; int d_base; // base is used with arrays. It provides a base // location from where index operations start to // count. public: AutoPtr(); // Default constructor explicit AutoPtr(Data *data); // Receive one allocated Data element AutoPtr(Data *data, size_t size); // Array of n Data elements AutoPtr(AutoPtr &other); // Copy constructor AutoPtr(AutoPtr &&other); // Move constructor ~AutoPtr(); AutoPtr &operator=(AutoPtr &other); Data &operator*(); Data *operator->(); Data *get(); // same as operator-> Data *release(); // lose one reference count Data *releaseAll(); // lose all references void reset(Data *data, size_t size = 0); // lose one reference, // reassign data[size] or // data if size == 0 void resetAll(Data *data, size_t size = 0); // new data[size] or data // if size == 0 Data &operator[](int idx); AutoPtr &operator+=(int idx); AutoPtr &operator-=(int idx); AutoPtr operator+(int idx); AutoPtr operator-(int idx); private: void destroy(); void copy(AutoPtr &other); }; // RefData members: template AutoPtr::RefData::RefData() : d_data(0), d_size(0) {} template AutoPtr::RefData::RefData(Data *data, size_t size) : d_data(data), d_size(size) {} template inline AutoPtr::RefData::~RefData() { destroy(); } template RefCount *AutoPtr::RefData::clone() const { Data *data; if (!d_size) data = new Data(*d_data); else { data = new Data[d_size]; std::copy(d_data, d_data + d_size, data); } return new RefData(d_data, d_size); } template inline Data *AutoPtr::RefData::get(int idx) { return d_data + idx; } template Data *AutoPtr::RefData::releaseOne() { Data *ret; if (refcount() == 1) { ret = d_data; d_data = 0; } else { if (!d_size) ret = new Data(*d_data); else { ret = new Data[d_size]; for (size_t idx = 0; idx < d_size; ++idx) ret[idx] = d_data[idx]; } } release(); return ret; } template Data *AutoPtr::RefData::releaseAll() { Data *ret = d_data; d_data = 0; release(); return ret; } template void AutoPtr::RefData::reset(Data *data, size_t size) { destroy(); d_data = data; d_size = size; } template void AutoPtr::RefData::destroy() { if (d_size == 0) delete d_data; else delete [] d_data; // maybe add facility for double pointers, // which will delete the individual data // elements? } // AutoPtr members template // Default constructor AutoPtr::AutoPtr() : d_data(new RefData()), d_base(0) {} template // One data element AutoPtr::AutoPtr(Data *data) : d_data(new RefData(data, 0)), d_base(0) {} template // Array of `size' data elements AutoPtr::AutoPtr(Data *data, size_t size) : d_data(new RefData(data, size)), d_base(0) {} template // Copy constructor inline AutoPtr::AutoPtr(AutoPtr &other) { copy(other); } template // Move constructor inline AutoPtr::AutoPtr(AutoPtr &&tmp) : d_data(tmp.d_datao), d_base(tmp.d_base) { tmp.d_data = 0; } template // destructor inline AutoPtr::~AutoPtr() { if (d_data) destroy(); } template // Assignment operator AutoPtr &AutoPtr::operator=(AutoPtr &other) { if (this != &other) { destroy(); copy(other); } return *this; } template // Dereference operator inline Data &AutoPtr::operator*() { return *d_data->get(d_base); } template // Pointer operator inline Data *AutoPtr::operator->() { return d_data->get(d_base); } template // get() member inline Data *AutoPtr::get() { return d_data->get(d_base); } template // lose one share count, return alloc. copy inline Data *AutoPtr::release() { return d_data->releaseOne(); } template // lose all shares, return alloc. data inline Data *AutoPtr::releaseAll() { return d_data->releaseAll(); } template // lose one share count, point to alloc. copy void AutoPtr::reset(Data *data, size_t size) { d_data->release(); d_data = new RefData(data, size); d_base = 0; } template // redefine data for all sharing objects void AutoPtr::resetAll(Data *data, size_t size) { d_data->reset(data, size); d_base = 0; } template void AutoPtr::copy(AutoPtr &other) { d_data = RefData::share(other.d_data); d_base = other.d_base; } template inline void AutoPtr::destroy() { d_data->release(); } template inline Data &AutoPtr::operator[](int idx) { return *d_data->get(d_base + idx); } template AutoPtr &AutoPtr::operator+=(int idx) { d_base += idx; return *this; } template inline AutoPtr AutoPtr::operator+(int idx) { return AutoPtr(*this) += idx; } template inline AutoPtr operator+(int idx, AutoPtr &rhs) { return AutoPtr(rhs) += idx; } template inline AutoPtr &AutoPtr::operator-=(int idx) { return *this += -idx; } template inline AutoPtr AutoPtr::operator-(int idx) { return AutoPtr(*this) -= idx; } } // FBB bobcat-3.19.01/base64streambufbase/0000755000175000017500000000000012244427062015736 5ustar frankfrankbobcat-3.19.01/base64streambufbase/doencrypt.cc0000644000175000017500000000017412222576533020262 0ustar frankfrank#include "base64streambufbase.ih" void Base64StreambufBase::doEncrypt() { d_action = &Base64StreambufBase::encrypt; } bobcat-3.19.01/base64streambufbase/base64streambufbase0000644000175000017500000000226512244427062021516 0ustar frankfrank#ifndef INCLUDED_BOBCAT_BASE64STREAMBUFBASE_ #define INCLUDED_BOBCAT_BASE64STREAMBUFBASE_ #include #include #include namespace FBB { namespace IUO // the facilities defined here are not further documented: { // the Base64StreambufBase class defined below should be // used by IBase64Streambuf only. class Base64StreambufBase: public FBB::IFilterStreambuf { std::istream &d_in; bool (Base64StreambufBase::*d_action)(); size_t d_bufSize; std::string d_buffer; bool d_allDone = false; static std::string const s_tabStr; public: Base64StreambufBase(std::istream &in, size_t bufSize); protected: void doEncrypt(); void doDecrypt(); private: bool filter(char const **srcBegin, char const **srcEnd) override; bool encrypt(); // false means: don't call again, but there // may still be input waiting in d_buffer bool decrypt(); template static int bits(int value); static size_t indexOf(int ch); }; #include "bits.f" } // IUO } // FBB #endif bobcat-3.19.01/base64streambufbase/decrypt.cc0000644000175000017500000000152612222576533017727 0ustar frankfrank#include "base64streambufbase.ih" #include bool Base64StreambufBase::decrypt() { while (true) { int b0 = d_in.get(); if (b0 == '\n') b0 = d_in.get(); if (s_tabStr.find(b0) == string::npos) { d_in.unget(); return false; } int b1 = d_in.get(); int b2 = d_in.get(); int b3 = d_in.get(); b0 = indexOf(b0); b1 = indexOf(b1); d_buffer.push_back((b0 << 2) | bits<4, 2>(b1)); if (b2 == '=') return false; b2 = indexOf(b2); d_buffer.push_back(bits<0, 4, 4>(b1) | bits<2, 4>(b2)); if (b3 == '=') return false; d_buffer.push_back(bits<0, 2, 6>(b2) | indexOf(b3)); if (d_buffer.size() > 100) return true; } } bobcat-3.19.01/base64streambufbase/base64streambufbase1.cc0000644000175000017500000000024212222576533022160 0ustar frankfrank#include "base64streambufbase.ih" Base64StreambufBase::Base64StreambufBase(std::istream &in, size_t bufSize) : IFilterStreambuf(bufSize), d_in(in) {} bobcat-3.19.01/base64streambufbase/base64streambufbase.ih0000644000175000017500000000013712222576533022115 0ustar frankfrank#include "base64streambufbase" using namespace std; using namespace FBB; using namespace IUO; bobcat-3.19.01/base64streambufbase/bits.f0000644000175000017500000000027212223023055017036 0ustar frankfranktemplate inline int Base64StreambufBase::bits(int value) { return value == EOF ? 0 : (value & ((1 << (from + size)) - 1)) >> from << shl; } bobcat-3.19.01/base64streambufbase/encrypt.cc0000644000175000017500000000152712222576533017742 0ustar frankfrank #include "base64streambufbase.ih" bool Base64StreambufBase::encrypt() { while (true) { int c0 = d_in.get(); if (!d_in) return d_buffer.size(); int c1 = d_in.get(); int c2 = d_in.get(); d_buffer.push_back(s_tabStr[ bits<2, 6>(c0) ]); d_buffer.push_back(s_tabStr[ bits<0, 2, 4>(c0) | bits<4, 4>(c1) ]); if (c1 == EOF) { d_buffer += "==\n"; return true; } d_buffer.push_back(s_tabStr[ bits<0, 4, 2>(c1) | bits<6, 2>(c2) ]); if (c2 == EOF) { d_buffer += "=\n"; return true; } d_buffer.push_back(s_tabStr[ bits<0, 6>(c2)]); if (d_buffer.size() == 76) { d_buffer.push_back('\n'); return true; } } } bobcat-3.19.01/base64streambufbase/data.cc0000644000175000017500000000033012222576533017156 0ustar frankfrank#include "base64streambufbase.ih" string const Base64StreambufBase::s_tabStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; bobcat-3.19.01/base64streambufbase/dodecrypt.cc0000644000175000017500000000021712222576533020246 0ustar frankfrank#include "base64streambufbase.ih" void Base64StreambufBase::doDecrypt() { d_action = &Base64StreambufBase::decrypt; // setBuffer(); } bobcat-3.19.01/base64streambufbase/indexof.cc0000644000175000017500000000032112222576533017701 0ustar frankfrank#include "base64streambufbase.ih" size_t Base64StreambufBase::indexOf(int ch) { size_t ret = s_tabStr.find(ch); if (ret == string::npos) throw "Infile not base64 encoded"; return ret; } bobcat-3.19.01/base64streambufbase/filter.cc0000644000175000017500000000054212222576533017537 0ustar frankfrank#include "base64streambufbase.ih" #include bool Base64StreambufBase::filter(char const **srcBegin, char const **srcEnd) { if (d_allDone) return false; d_buffer.clear(); d_allDone = (this->*d_action)() == false; *srcBegin = d_buffer.data(); *srcEnd = *srcBegin + d_buffer.size(); return d_buffer.size(); } bobcat-3.19.01/bigint/0000755000175000017500000000000012257325714013367 5ustar frankfrankbobcat-3.19.01/bigint/operatornegate.cc0000644000175000017500000000016512222576523016715 0ustar frankfrank#include "bigint.ih" BigInt BigInt::operator-() const { BigInt tmp(*this); tmp.negate(); return tmp; } bobcat-3.19.01/bigint/diophantus1.cc0000644000175000017500000000077612222576523016145 0ustar frankfrank#include "bigint.ih" long long BigInt::diophantus(long long *factor1, long long *factor2, long long const &value1, long long const &value2) { if (long long modulo = value1 % value2) { long long nestedFactor1; long long gcd = diophantus(&nestedFactor1, factor2, value2, modulo); *factor1 = *factor2; *factor2 = nestedFactor1 - (value1 / value2) * *factor2; return gcd; } *factor1 = 0; *factor2 = 1; return value2; } bobcat-3.19.01/bigint/checked4.cc0000644000175000017500000000062112222576523015345 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::checked4(int (*BN_op)(BIGNUM *, BIGNUM const *, BIGNUM const *, BN_CTX *), BigInt const &rhs, char const *op) { BNCTX ctx; if ((*BN_op)(&d_bn, &d_bn, &rhs.d_bn, ctx) != 1) throw Exception() << "BigInt " << op << " failed"; return *this; } bobcat-3.19.01/bigint/rand.cc0000644000175000017500000000032412222576523014617 0ustar frankfrank#include "bigint.ih" BigInt BigInt::rand(size_t size, Msb msb, Lsb lsb) { BigInt ret; if (BN_rand(&ret.d_bn, size, msb, lsb) != 1) throw Exception() << "BigInt::rand() failed"; return ret; } bobcat-3.19.01/bigint/bit1.cc0000644000175000017500000000014212222576523014530 0ustar frankfrank#include "bigint.ih" BigInt::Bit::Bit(BigInt &bi, size_t idx) : d_bi(bi), d_idx(idx) {} bobcat-3.19.01/bigint/bigint0000644000175000017500000002511512224015015014552 0ustar frankfrank#ifndef INCLUDED_BOBCAT_BIGINT_ #define INCLUDED_BOBCAT_BIGINT_ #include #include #include namespace FBB { class BigInt { friend std::ostream &operator<<(std::ostream &out, BigInt const &bn); BIGNUM d_bn; public: typedef BN_ULONG Word; enum Msb { MSB_UNKNOWN = -1, MSB_IS_ONE, TOP_TWO_BITS_ONE }; enum Lsb { EVEN, ODD, }; enum PrimeType { ANY = false, SAFE = true }; BigInt(); // 1 BigInt(BigInt const &other); // 3 template // promotion OK BigInt(Type value); explicit BigInt(BIGNUM const &bignum); // 2 explicit BigInt(BIGNUM const *bignum); // 4 BigInt(char const *bigEndian, size_t length, bool negative = false); // 5 explicit BigInt(std::string const &bigEndian, bool negative = false); // 6 ~BigInt(); BigInt &operator=(BigInt const &other); BigInt operator-() const; BigInt &negate(); BigInt negatec() const; BigInt &setNegative(bool negative); BigInt setNegativec(bool negative) const; bool isNegative() const; // .f BigInt &tildeBits(); BigInt tildeBitsc() const; BigInt &tildeInt(); BigInt tildeIntc() const; BigInt &operator--(); // opdec.f BigInt operator--(int); BigInt &operator++(); // opinc.f BigInt operator++(int); class Bit; Bit operator[](size_t idx); // opindex.f // non-const BigInts: // distinguishes lhs/rhs int operator[](size_t idx) const; // opindexc.f // only rhs for const BigInts class Bit { friend Bit BigInt::operator[](size_t idx); friend std::ostream &operator<<(std::ostream &out, Bit const &bit); BigInt &d_bi; size_t d_idx; public: operator bool() const; Bit &operator=(bool rhs); // assign a bit Bit &operator&=(bool rhs); // bit_and a bit Bit &operator|=(bool rhs); // bit_or a bit Bit &operator^=(bool rhs); // bit_xor a bit private: Bit(BigInt &bi, size_t idx); }; char *bigEndian() const; BigInt &operator+=(BigInt const &rhs); // opaddis.f BigInt &addMod(BigInt const &rhs, BigInt const &mod); // .f BigInt addModc(BigInt const &rhs, BigInt const &mod) const; BigInt &operator-=(BigInt const &rhs); // opsubis.f BigInt &subMod(BigInt const &rhs, BigInt const &mod); // .f BigInt subModc(BigInt const &rhs, BigInt const &mod) const; BigInt &operator*=(BigInt const &rhs); BigInt &mulMod(BigInt const &rhs, BigInt const &mod); // .f BigInt mulModc(BigInt const &rhs, BigInt const &mod) const; BigInt &operator%=(BigInt const &rhs); BigInt &operator/=(BigInt const &rhs); // integer division, // integer division, also // returning remainder BigInt &div(BigInt *remainder, BigInt const &rhs); BigInt divc(BigInt *remainder, BigInt const &rhs) const; BigInt &sqr(); BigInt sqrc() const; BigInt &sqrMod(BigInt const &mod); // .f BigInt sqrModc(BigInt const &mod) const; BigInt &operator&=(BigInt const &rhs); BigInt &operator|=(BigInt const &rhs); BigInt &operator^=(BigInt const &rhs); bool isZero() const; // .f bool isOne() const; // .f bool isOdd() const; // .f unsigned long ulong() const; // .f BIGNUM const &bignum() const; // .f size_t sizeInBytes() const; // .f size_t size() const; // .f size_t nWords() const; // .f static size_t constexpr sizeOfWord(); // .f Word at(size_t index) const; void setWord(size_t index, Word value); int compare(BigInt const &other) const; // .f int uCompare(BigInt const &other) const; // .f long long diophantus(long long *factor1, long long *factor2, long long const &value1, long long const &value2); BigInt diophantus(BigInt *factor1, BigInt *factor2, BigInt const &value1, BigInt const &value2); BigInt &exp(BigInt const &exponent); BigInt expc(BigInt const &exponent) const; BigInt &expMod(BigInt const &exponent, BigInt const &mod); BigInt expModc(BigInt const &exponent, BigInt const &mod) const; BigInt &gcd(BigInt const &rhs); BigInt gcdc(BigInt const &rhs) const; BigInt &inverseMod(BigInt const &mod); BigInt inverseModc(BigInt const &mod) const; BigInt &isqrt(); BigInt isqrtc() const; static BigInt rand(size_t bitsSize, Msb msb = MSB_IS_ONE, Lsb lsb = ODD); static BigInt randRange(BigInt const &max); static BigInt setBigEndian(std::string const &bytes); static BigInt pseudoRand(size_t bitsSize, Msb msb = MSB_IS_ONE, Lsb lsb = ODD); static BigInt pseudoRandRange(BigInt const &max); static BigInt prime(size_t nBits, BigInt const *add = 0, BigInt const *rem = 0, PrimeType primeType = ANY); static BigInt fromText(std::string const &text, int mode = 0); BigInt &clearBit(size_t index); BigInt clearBit(size_t index) const; bool hasBit(size_t index) const; // .f BigInt &maskBits(size_t lowerNBits); BigInt maskBitsc(size_t lowerNBits) const; BigInt &setBit(size_t index); BigInt setBitc(size_t index) const; BigInt &setBit(size_t index, bool value); BigInt setBitc(size_t index, bool value) const; BigInt &lshift(); BigInt lshiftc() const; BigInt &lshift(size_t nBits); BigInt lshiftc(size_t nBits) const; BigInt &operator<<=(size_t nBits); // opshlis.f BigInt &rshift(); BigInt rshiftc() const; BigInt &rshift(size_t nBits); BigInt rshiftc(size_t nBits) const; BigInt &operator>>=(size_t nBits); // opshris.f void swap(BigInt &other); private: void mod_inverse(BigInt *ret, BigInt const &mod) const; std::ostream &insertInto(std::ostream &out) const; static char *bn2oct(BIGNUM const *bn); void copy(BIGNUM *lhs, BIGNUM const &rhs); void nWordsCheck(size_t index) const; BigInt &checked1( int (*BN_op)(BIGNUM *, BIGNUM const *, BIGNUM const *), BigInt const &rhs, char const *op); BigInt &checked2(int (*BN_op)(BIGNUM *, BIGNUM const *, BIGNUM const *, BIGNUM const *, BN_CTX *), BigInt const &rhs, BigInt const &mod, char const *op); void checked3(BIGNUM *div, BIGNUM *rem, BigInt const &rhs, char const *op) const; BigInt &checked4(int (*BN_op)(BIGNUM *, BIGNUM const *, BIGNUM const *, BN_CTX *), BigInt const &rhs, char const *op); static void primeCallback(int reason, int primeNr, void *primeBase); static bool addDigit(char ch, BigInt &ret, BigInt const &radix, int (*pConv)(int)); }; template BigInt::BigInt(Type value) { bool negative = value < 0; if (negative) value = -value; BN_init(&d_bn); BN_set_word(&d_bn, static_cast(value)); if (negative) negate(); } #include "nwords.f" #include "addmod.f" #include "bignum.f" #include "compare.f" #include "hasbit.f" #include "isnegative.f" #include "isodd.f" #include "isone.f" #include "iszero.f" #include "mulmod.f" #include "opaddis.f" #include "opbool.f" #include "opdec.f" #include "opinc.f" #include "opindex.f" #include "opindexc.f" #include "opshlis.f" #include "opshris.f" #include "opsubis.f" #include "size.f" #include "sizeinbytes.f" #include "sizeofword.f" #include "sqrmod.f" #include "submod.f" #include "ucompare.f" // Free functions BigInt operator*(BigInt const &lhs, BigInt const &rhs); BigInt operator/(BigInt const &lhs, BigInt const &rhs); BigInt operator%(BigInt const &lhs, BigInt const &rhs); BigInt operator+(BigInt const &lhs, BigInt const &rhs); BigInt operator-(BigInt const &lhs, BigInt const &rhs); BigInt operator>>(BigInt const &lhs, size_t rhs); BigInt operator<<(BigInt const &lhs, size_t rhs); BigInt operator|(BigInt const &lhs, BigInt const &rhs); BigInt operator&(BigInt const &lhs, BigInt const &rhs); BigInt operator^(BigInt const &lhs, BigInt const &rhs); BigInt gcd(BigInt const &lhs, BigInt const &rhs); BigInt inverseMod(BigInt const &lhs, BigInt const &mod); std::istream &operator>>(std::istream &out, BigInt &bn); int isoctdigit(int ch); #include "opgreater.f" // > #include "opgreaterequal.f" // >= #include "opinsert.f" // ostream << #include "opisequal.f" // == #include "opisunequal.f" // != #include "opless.f" // < #include "oplessequal.f" // <= } // namespace FBB #endif bobcat-3.19.01/bigint/bigint2.cc0000644000175000017500000000015412222576523015232 0ustar frankfrank#include "bigint.ih" BigInt::BigInt(BIGNUM const &bignum) { BN_init(&d_bn); copy(&d_bn, bignum); } bobcat-3.19.01/bigint/isqrt.cc0000644000175000017500000000163512222576523015043 0ustar frankfrank#include "bigint.ih" /* Newton's algorithm: x[i+1] = (x[i] + value / x[i]) / 2 until convergence. the returned value is the biggest int `ret' for which ret * ret <= value With integral values the algorithm may be trapped in an endless loop where the next value exceeds the previous value (this happens, e.g., with value = 15). This is handled by testing for this condition, rather than convergence. Initially x[0] = value */ BigInt &BigInt::isqrt() { BigInt org(*this); BigInt tmp; BigInt *step = this; BigInt *next = &tmp; if (isZero() || isNegative()) throw Exception(1) << "BigInt::isqrt: BigInt must be positive"; while (true) { *next = *step + org / *step; next->rshift(); if (*next >= *step) break; fswap(step, next); } if (this != step) *this = *step; return *this; } bobcat-3.19.01/bigint/setbit2.cc0000644000175000017500000000020412222576523015244 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::setBit(size_t index, bool value) { return value ? setBit(index) : clearBit(index); } bobcat-3.19.01/bigint/nwordscheck.cc0000644000175000017500000000037712224015005016176 0ustar frankfrank#include "bigint.ih" void BigInt::nWordsCheck(size_t index) const { if (index >= nWords()) throw Exception() << "BigInt: word index " << index << " exceeds " << nWords(); } bobcat-3.19.01/bigint/destructor.cc0000644000175000017500000000010012222576523016061 0ustar frankfrank#include "bigint.ih" BigInt::~BigInt() { BN_free(&d_bn); } bobcat-3.19.01/bigint/operatorand.cc0000644000175000017500000000024112222576523016207 0ustar frankfrank#include "bigint.ih" namespace FBB { BigInt operator&(BigInt const &lhs, BigInt const &rhs) { BigInt tmp(lhs); tmp &= rhs; return tmp; } } // FBB bobcat-3.19.01/bigint/clearbit.cc0000644000175000017500000000016412222576523015462 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::clearBit(size_t index) { BN_clear_bit(&d_bn, index); return *this; } bobcat-3.19.01/bigint/operatormodis.cc0000644000175000017500000000017612222576523016567 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::operator%=(BigInt const &rhs) { checked3(0, &d_bn, rhs, "%="); return *this; } bobcat-3.19.01/bigint/size.f0000644000175000017500000000010612223023055014467 0ustar frankfrankinline size_t BigInt::size() const { return BN_num_bits(&d_bn); } bobcat-3.19.01/bigint/sizeofword.f0000644000175000017500000000010312224006661015712 0ustar frankfranksize_t constexpr BigInt::sizeOfWord() { return sizeof(Word); } bobcat-3.19.01/bigint/setnegative.cc0000644000175000017500000000017612222576523016216 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::setNegative(bool negative) { BN_set_negative(&d_bn, negative); return *this; } bobcat-3.19.01/bigint/opisequal.f0000644000175000017500000000014412223023055015521 0ustar frankfrankinline bool operator==(BigInt const &lhs, BigInt const &rhs) { return lhs.compare(rhs) == 0; } bobcat-3.19.01/bigint/opindexc.f0000644000175000017500000000011412223023055015325 0ustar frankfrankinline int BigInt::operator[](size_t idx) const { return hasBit(idx); } bobcat-3.19.01/bigint/submod.f0000644000175000017500000000017512223023055015014 0ustar frankfrankinline BigInt &BigInt::subMod(BigInt const &rhs, BigInt const &mod) { return checked2(BN_mod_sub, rhs, mod, "subMod"); } bobcat-3.19.01/bigint/opaddis.f0000644000175000017500000000014012223023055015136 0ustar frankfrankinline BigInt &BigInt::operator+=(BigInt const &rhs) { return checked1(BN_add, rhs, "+"); } bobcat-3.19.01/bigint/operatoradd.cc0000644000175000017500000000023212222576523016175 0ustar frankfrank#include "bigint.ih" namespace FBB { BigInt operator+(BigInt const &lhs, BigInt const &rhs) { BigInt tmp(lhs); tmp += rhs; return tmp; } } bobcat-3.19.01/bigint/opbnctxptr.f0000644000175000017500000000007012223023055015720 0ustar frankfrankinline BNCTX::operator BN_CTX *() { return d_ctx; } bobcat-3.19.01/bigint/expmodc.cc0000644000175000017500000000025012222576523015330 0ustar frankfrank#include "bigint.ih" BigInt BigInt::expModc(BigInt const &exponent, BigInt const &mod) const { BigInt ret(*this); ret.expMod(exponent, mod); return ret; } bobcat-3.19.01/bigint/modinverse.cc0000644000175000017500000000034312222576523016047 0ustar frankfrank#include "bigint.ih" void BigInt::mod_inverse(BigInt *ret, BigInt const &mod) const { BNCTX ctx; if (BN_mod_inverse(&ret->d_bn, &d_bn, &mod.d_bn, ctx) == 0) throw Exception() << "BigInt::inverseMod failed"; } bobcat-3.19.01/bigint/rshiftc1.cc0000644000175000017500000000016412222576523015420 0ustar frankfrank#include "bigint.ih" BigInt BigInt::rshiftc() const { BigInt ret(*this); ret.rshift(); return ret; } bobcat-3.19.01/bigint/div.cc0000644000175000017500000000023212222576523014453 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::div(BigInt *remainder, BigInt const &rhs) { checked3(&d_bn, &remainder->d_bn, rhs, "div"); return *this; } bobcat-3.19.01/bigint/opsubis.f0000644000175000017500000000014012223023055015177 0ustar frankfrankinline BigInt &BigInt::operator-=(BigInt const &rhs) { return checked1(BN_sub, rhs, "-"); } bobcat-3.19.01/bigint/checked1.cc0000644000175000017500000000045612222576523015350 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::checked1( int (*BN_op)(BIGNUM *, const BIGNUM *, const BIGNUM *), BigInt const &rhs, char const *op) { if ((*BN_op)(&d_bn, &d_bn, &rhs.d_bn) != 1) throw Exception() << "BigInt " << op << " failed"; return *this; } bobcat-3.19.01/bigint/bigint5.cc0000644000175000017500000000033412222576523015235 0ustar frankfrank#include "bigint.ih" BigInt::BigInt(char const *bigEndian, size_t length, bool negative) { BN_bin2bn(reinterpret_cast(bigEndian), length, &d_bn); setNegative(negative); } bobcat-3.19.01/bigint/opisunequal.f0000644000175000017500000000014312223023055016063 0ustar frankfrankinline bool operator!=(BigInt const &lhs, BigInt const &rhs) { return lhs.compare(rhs) != 0; } bobcat-3.19.01/bigint/ulong.f0000644000175000017500000000011612223023055014642 0ustar frankfrankinline unsigned long BigInt::ulong() const { return BN_get_word(&d_bn); } bobcat-3.19.01/bigint/operatorandis.cc0000644000175000017500000000150012222576523016542 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::operator&=(BigInt const &rhs) { setNegative(isNegative() && rhs.isNegative()); size_t nMin = min(sizeInBytes(), rhs.sizeInBytes()); size_t nMax = max(sizeInBytes(), rhs.sizeInBytes()); unsigned char small[nMin]; unsigned char large[nMax]; BIGNUM const *bSmall; BIGNUM const *bLarge; if (sizeInBytes() < rhs.sizeInBytes()) { bSmall = &d_bn; bLarge = &rhs.d_bn; } else { bLarge = &d_bn; bSmall = &rhs.d_bn; } BN_bn2bin(bSmall, small); BN_bn2bin(bLarge, large); unsigned char *largePtr = large + nMax - nMin; for (size_t idx = 0; idx != nMin; ++idx) // AND bytes 0 to nMin small[idx] &= largePtr[idx]; BN_bin2bn(small, nMin, &d_bn); return *this; } bobcat-3.19.01/bigint/clearbitc.cc0000644000175000017500000000022212222576523015620 0ustar frankfrank#include "bigint.ih" BigInt BigInt::clearBit(size_t index) const { BigInt ret(*this); BN_clear_bit(&ret.d_bn, index); return ret; } bobcat-3.19.01/bigint/rshiftc2.cc0000644000175000017500000000020312222576523015413 0ustar frankfrank#include "bigint.ih" BigInt BigInt::rshiftc(size_t nBits) const { BigInt ret(*this); ret.rshift(nBits); return ret; } bobcat-3.19.01/bigint/bigint3.cc0000644000175000017500000000015712222576523015236 0ustar frankfrank#include "bigint.ih" BigInt::BigInt(BigInt const &other) { BN_init(&d_bn); copy(&d_bn, other.d_bn); } bobcat-3.19.01/bigint/bitoperatoris.cc0000644000175000017500000000017012222576523016560 0ustar frankfrank#include "bigint.ih" BigInt::Bit &BigInt::Bit::operator=(bool rhs) { d_bi.setBit(d_idx, rhs); return *this; } bobcat-3.19.01/bigint/operatorsub.cc0000644000175000017500000000023212222576523016236 0ustar frankfrank#include "bigint.ih" namespace FBB { BigInt operator-(BigInt const &lhs, BigInt const &rhs) { BigInt tmp(lhs); tmp -= rhs; return tmp; } } bobcat-3.19.01/bigint/rshift1.cc0000644000175000017500000000024312222576523015253 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::rshift() { if (!BN_rshift1(&d_bn, &d_bn)) throw Exception() << "BigInt::rshift() failed"; return *this; } bobcat-3.19.01/bigint/sqrc.cc0000644000175000017500000000015412222576523014644 0ustar frankfrank#include "bigint.ih" BigInt BigInt::sqrc() const { BigInt ret(*this); ret.sqr(); return ret; } bobcat-3.19.01/bigint/prime.cc0000644000175000017500000000071212222576523015010 0ustar frankfrank#include "bigint.ih" BigInt BigInt::prime(size_t nBits, BigInt const *mod, BigInt const *rem, PrimeType primeType) { BigInt ret; bool useArgs = mod != 0 && rem != 0; if ( BN_generate_prime(&ret.d_bn, nBits, primeType, useArgs ? &(mod->d_bn) : 0, useArgs ? &(rem->d_bn) : 0, 0, 0) == 0 ) throw Exception() << "BigInt::prime() failed"; return ret; } bobcat-3.19.01/bigint/isnegative.f0000644000175000017500000000012312223023055015652 0ustar frankfrankinline bool BigInt::isNegative() const { return BN_is_negative(&this->d_bn); } bobcat-3.19.01/bigint/rshift2.cc0000644000175000017500000000030712222576523015255 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::rshift(size_t nBits) { if (!BN_rshift(&this->d_bn, &this->d_bn, nBits)) throw Exception() << "BigInt::rshift(size_t) failed"; return *this; } bobcat-3.19.01/bigint/submodc.cc0000644000175000017500000000023712222576523015332 0ustar frankfrank#include "bigint.ih" BigInt BigInt::subModc(BigInt const &rhs, BigInt const &mod) const { BigInt ret(*this); ret.subMod(rhs, mod); return ret; } bobcat-3.19.01/bigint/operatormod.cc0000644000175000017500000000023212222576523016224 0ustar frankfrank#include "bigint.ih" namespace FBB { BigInt operator%(BigInt const &lhs, BigInt const &rhs) { BigInt tmp(lhs); tmp %= rhs; return tmp; } } bobcat-3.19.01/bigint/destructor.f0000644000175000017500000000006312223023055015715 0ustar frankfrankinline BNCTX::~BNCTX() { BN_CTX_free(d_ctx); } bobcat-3.19.01/bigint/bn2oct.cc0000644000175000017500000000204312222576523015062 0ustar frankfrank#include "bigint.ih" char *BigInt::bn2oct(BIGNUM const *bn) { size_t nBits = (((BN_num_bits(bn)) + 2) / 3) * 3; char *ret = new char[nBits + 3]; // 1 for the -, 1 for the 0 // 1 for the asciiZ char *cp = ret; if (BN_is_negative(bn)) *cp++ = '-'; *cp++ = '0'; // initial 0 indicating octal for (; nBits; ) // proceed until 1st value != 0 { nBits -= 3; if (int value = (BN_is_bit_set(bn, nBits + 2) << 2) + (BN_is_bit_set(bn, nBits + 1) << 1) + BN_is_bit_set(bn, nBits)) { *cp++ = '0' + value; break; } } for (; nBits; ) // do the rest { nBits -= 3; *cp++ = '0' + (BN_is_bit_set(bn, nBits + 2) << 2) + (BN_is_bit_set(bn, nBits + 1) << 1) + BN_is_bit_set(bn, nBits); } *cp = 0; return ret; } bobcat-3.19.01/bigint/diophantus2.cc0000644000175000017500000000077512222576523016145 0ustar frankfrank#include "bigint.ih" BigInt BigInt::diophantus(BigInt *factor1, BigInt *factor2, BigInt const &value1, BigInt const &value2) { BigInt modulo = value1 % value2; if (not modulo.isZero()) { BigInt nestedFactor1; BigInt gcd = diophantus(&nestedFactor1, factor2, value2, modulo); *factor1 = *factor2; *factor2 = nestedFactor1 - (value1 / value2) * *factor2; return gcd; } *factor1 = 0; *factor2 = 1; return value2; } bobcat-3.19.01/bigint/operatorinsertbit.cc0000644000175000017500000000024412222576523017453 0ustar frankfrank#include "bigint.ih" namespace FBB { ostream &operator<<(ostream &out, BigInt::Bit const &bit) { return out << (bit.d_bi.hasBit(bit.d_idx) ? '1' : '0'); } } bobcat-3.19.01/bigint/lshift1.cc0000644000175000017500000000024312222576523015245 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::lshift() { if (!BN_lshift1(&d_bn, &d_bn)) throw Exception() << "BigInt::lshift() failed"; return *this; } bobcat-3.19.01/bigint/opbool.f0000644000175000017500000000011512223023055015007 0ustar frankfrankinline BigInt::Bit::operator bool() const { return d_bi.hasBit(d_idx); } bobcat-3.19.01/bigint/setnegativec.cc0000644000175000017500000000022112222576523016350 0ustar frankfrank#include "bigint.ih" BigInt BigInt::setNegativec(bool negative) const { BigInt ret(*this); ret.setNegative(negative); return ret; } bobcat-3.19.01/bigint/exp.cc0000644000175000017500000000032112222576523014464 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::exp(BigInt const &exponent) { BNCTX ctx; if (!BN_exp(&d_bn, &d_bn, &exponent.d_bn, ctx)) throw Exception() << "BigInt exp() failed"; return *this; } bobcat-3.19.01/bigint/setbitc.cc0000644000175000017500000000020312222576523015324 0ustar frankfrank#include "bigint.ih" BigInt BigInt::setBitc(size_t index) const { BigInt ret(*this); ret.setBit(index); return ret; } bobcat-3.19.01/bigint/bigint.ih0000644000175000017500000000126312223023055015151 0ustar frankfrank#include "bigint" #include #include #include #include #include #include namespace FBB { class BNCTX { BN_CTX *d_ctx; public: BNCTX(); // .i ~BNCTX(); // destructor.i void verify(); operator BN_CTX *(); // opbnctxptr.i private: BNCTX(BNCTX const &other) = delete; BNCTX &operator=(BNCTX const &other) = delete; }; #include "bnctx.f" #include "destructor.f" #include "opbnctxptr.f" } // namespace FBB using namespace std; using namespace FBB; bobcat-3.19.01/bigint/operatorrshift.cc0000644000175000017500000000023112222576523016743 0ustar frankfrank#include "bigint.ih" namespace FBB { BigInt operator>>(BigInt const &lhs, size_t nBits) { BigInt tmp(lhs); tmp >>= nBits; return tmp; } } bobcat-3.19.01/bigint/checked2.cc0000644000175000017500000000065112222576523015346 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::checked2( int (*BN_op)(BIGNUM *, BIGNUM const *, BIGNUM const *, BIGNUM const *, BN_CTX *), BigInt const &rhs, BigInt const &mod, char const *op) { BNCTX ctx; if ((*BN_op)(&d_bn, &d_bn, &rhs.d_bn, &mod.d_bn, ctx) != 1) throw Exception() << "BigInt " << op << " failed"; return *this; } bobcat-3.19.01/bigint/operatorextract.cc0000644000175000017500000000157612222576523017133 0ustar frankfrank#include "bigint.ih" namespace FBB { std::istream &operator>>(std::istream &in, BigInt &bn) { string value; int flags = in.flags(); int (*charType)(int) = flags & ios::dec ? ::isdigit : flags & ios::hex ? ::isxdigit : FBB::isoctdigit; char c; in >> c; // skip ws in.putback(c); if (in.peek() == '-') { in.ignore(1); value = '-'; } bool validInput = false; while (true) { int ch = static_cast(in.peek()); if (not (*charType)(ch)) { if (!validInput) { in.setstate(ios::failbit); return in; } break; } in.get(); value += ch; validInput = true; } bn = BigInt::fromText(value, flags); return in; } } bobcat-3.19.01/bigint/addmod.f0000644000175000017500000000017512223023055014753 0ustar frankfrankinline BigInt &BigInt::addMod(BigInt const &rhs, BigInt const &mod) { return checked2(BN_mod_add, rhs, mod, "addMod"); } bobcat-3.19.01/bigint/setbit.cc0000644000175000017500000000026212222576523015166 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::setBit(size_t index) { if (!BN_set_bit(&this->d_bn, index)) throw Exception() << "BigInt::setBit failed"; return *this; } bobcat-3.19.01/bigint/fromtext.cc0000644000175000017500000000244112222576523015545 0ustar frankfrank#include "bigint.ih" // conversion stops at the first character outside of the expected range of // characters. BigInt BigInt::fromText(string const &text, int mode) { BigInt ret; if (not mode & (ios::hex | ios::oct | ios::dec)) mode = text.find_first_of("abcdefABCDEF") != string::npos ? ios::hex : text.find_first_of("89") == string::npos && text[0] == '0' ? ios::oct : ios::dec; BigInt radix(mode & ios::oct ? 8 : mode & ios::hex ? 16 : 10); bool negative = text[0] == '-'; int (*isFunction)(int) = mode & ios::oct ? isoctdigit : mode & ios::hex ? ::isxdigit : ::isdigit; auto iter = find_if( text.begin() + negative, text.end(), [&, isFunction](char ch) { return addDigit(ch, ret, radix, isFunction); } ); if (iter - (text.begin() + negative) == 0) throw Exception() << "fromText: text does not represent a BigInt value"; if (negative) ret.negate(); return ret; } bobcat-3.19.01/bigint/bigint4.cc0000644000175000017500000000015512222576523015235 0ustar frankfrank#include "bigint.ih" BigInt::BigInt(BIGNUM const *bignum) { BN_init(&d_bn); copy(&d_bn, *bignum); } bobcat-3.19.01/bigint/copy.cc0000644000175000017500000000024712222576523014651 0ustar frankfrank#include "bigint.ih" void BigInt::copy(BIGNUM *lhs, BIGNUM const &rhs) { if (!BN_copy(lhs, &rhs)) throw Exception() << "BigInt: copying BigInt failed"; } bobcat-3.19.01/bigint/opless.f0000644000175000017500000000014212223023055015022 0ustar frankfrankinline bool operator<(BigInt const &lhs, BigInt const &rhs) { return lhs.compare(rhs) < 0; } bobcat-3.19.01/bigint/opgreaterequal.f0000644000175000017500000000014312223023055016536 0ustar frankfrankinline bool operator>=(BigInt const &lhs, BigInt const &rhs) { return lhs.compare(rhs) >= 0; } bobcat-3.19.01/bigint/isodd.f0000644000175000017500000000010312223023055014614 0ustar frankfrankinline bool BigInt::isOdd() const { return BN_is_odd(&d_bn); } bobcat-3.19.01/bigint/expc.cc0000644000175000017500000000021212222576523014626 0ustar frankfrank#include "bigint.ih" BigInt BigInt::expc(BigInt const &exponent) const { BigInt ret(*this); ret.exp(exponent); return ret; } bobcat-3.19.01/bigint/pseudorand.cc0000644000175000017500000000034712222576523016044 0ustar frankfrank#include "bigint.ih" BigInt BigInt::pseudoRand(size_t size, Msb msb, Lsb lsb) { BigInt ret; if (BN_pseudo_rand(&ret.d_bn, size, msb, lsb) != 1) throw Exception() << "BigInt::pseudoRand() failed"; return ret; } bobcat-3.19.01/bigint/oplessequal.f0000644000175000017500000000014312223023055016053 0ustar frankfrankinline bool operator<=(BigInt const &lhs, BigInt const &rhs) { return lhs.compare(rhs) <= 0; } bobcat-3.19.01/bigint/hasbit.f0000644000175000017500000000014112223023055014766 0ustar frankfrankinline bool BigInt::hasBit(size_t index) const { return BN_is_bit_set(&this->d_bn, index); } bobcat-3.19.01/bigint/sqrmodc.cc0000644000175000017500000000020612222576523015342 0ustar frankfrank#include "bigint.ih" BigInt BigInt::sqrModc(BigInt const &mod) const { BigInt ret(*this); ret.sqrMod(mod); return ret; } bobcat-3.19.01/bigint/operatorlshift.cc0000644000175000017500000000023112222576523016735 0ustar frankfrank#include "bigint.ih" namespace FBB { BigInt operator<<(BigInt const &lhs, size_t nBits) { BigInt tmp(lhs); tmp <<= nBits; return tmp; } } bobcat-3.19.01/bigint/negatec.cc0000644000175000017500000000016312222576523015302 0ustar frankfrank#include "bigint.ih" BigInt BigInt::negatec() const { BigInt ret(*this); ret.negate(); return ret; } bobcat-3.19.01/bigint/driver/0000755000175000017500000000000012224221447014652 5ustar frankfrankbobcat-3.19.01/bigint/driver/build0000755000175000017500000000102412224221432015666 0ustar frankfrank#!/bin/bash tput clear LIBS=" -lbobcat -lcrypto" GPP="g++ --std=c++0x" # WHEN LINKING TO A STATIC LIBRARY DON'T FORGET TO LINK AGAINST # crypto (-lcrypto) # CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp ${LIBS} -lbigint -s" # CMD="$GPP -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib ${LIBS} -s" # CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp ${LIBS} -s" CMD="$GPP -o driver -Wall -I../ driver.cc ../*.o ${LIBS} -s" CMD="$GPP -o driver -Wall *.cc ${LIBS} -s" echo $CMD $CMD || exit 1 echo Ready... driver bobcat-3.19.01/bigint/driver/driver.cc0000644000175000017500000001265312222576523016471 0ustar frankfrank#include #include #include #include "../bigint" #include using namespace std; using namespace FBB; void binary(BigInt const &bi) { cout << bi.size() << " bits: "; for (size_t idx = bi.sizeInBytes() * 8 ; idx--; ) cout << bi[idx]; cout << '\n'; } int main(int argc, char **argv) try { if (argc == 1) throw Errno(1, "Provide h (hex), o (oct), or d (dec) argument"); // BigInt value; // // int mode = argv[1][0]; // // cin >> // (mode == 'h' ? hex : mode == 'o' ? oct : dec) >> // value; // // if (cin.fail()) // cout << "Input failed\n"; // else // cout << '\n' << // value << '\n' << // oct << value << '\n' << // hex << value << '\n'; BigInt zero; // default construction of a BigInt cout << "Defaults to zero: " << zero << '\n'; BigInt other(zero); // Copycons cout << "Copying zero: " << other << '\n'; BigInt five(5); // Member template cout << "Member template constructs 5: " << five << '\n'; cout << "five.operator-(): " << -five << '\n'; cout << "five.negate(): " << five.negate() << '\n'; cout << "five.isNegative(): " << five.isNegative() << '\n'; five.setNegative(false); cout << "five.setNegative(false): negative? " << five.isNegative() << '\n'; cout << "five: " << five << ". "; binary(five); cout << "five.tildeBits(): " << five.tildeBits() << ". "; binary(five); five = 5; cout << "five.tildeInt(): " << five.tildeInt() << ". "; binary(five); cout << "++ --zero: " << ++ --zero << " (zero = " << zero << ")\n"; BigInt zeroOrg(zero--); cout << "zeroOrg(zero--): zeroOrg: " << zeroOrg << ", zero: " << zero << '\n'; five = 5; cout << "five: " << five << ". "; binary(five); cout << "five[1]: " << five[1] << '\n'; five[1] |= 1; cout << "five[1] |= 1: " << five[1] << '\n'; cout << "five: " << five << ". "; binary(five); five[1] ^= 1; cout << "five[1] ^= 1: " << five[1] << '\n'; cout << "five: " << five << ". "; binary(five); cout << "five[0] &= 1: " << (five[0] &= 1) << '\n'; cout << "five: " << five << ". "; binary(five); BigInt large(0x123456); cout << hex << "0x" << large << '\n'; char *bigEndian = large.bigEndian(); for (size_t idx = 0; idx < large.sizeInBytes(); ++idx) cout << "byte[" << idx << "]: 0x" << static_cast(static_cast(bigEndian[idx])) << '\n'; swap(bigEndian[0], bigEndian[large.sizeInBytes()-1]); string newValue(bigEndian, bigEndian + large.sizeInBytes()); delete[] bigEndian; large = BigInt::setBigEndian(newValue); cout << "Swapped lowest and highest bytes: 0x" << large << dec << '\n'; cout << "large = five: " << (large = five) << '\n'; cout << "large += large: " << (large += large) << '\n'; cout << "large.addMod(five, 13) : " << large.addMod(five, 13) << '\n'; large = 123456789; cout << "large (= 123456789) / 1234 = " << (large /= 1234) << '\n'; large = 123456789; BigInt remainder; large.div(&remainder, 1234); cout << "Remainder of the division: " << remainder << '\n'; cout << "GCD of " << large << " and 123 is: " << large.gcd(123) << '\n'; cout << "large.sqr(): " << large.sqr() << '\n'; cout << "large.sqrmod(" << "12345): " << large.sqrMod(12345) << '\n'; cout << "Binary |, & and ^ operations:\n"; large = 0x123; binary(large); binary(large | 0x111); binary(large ^ 0x111); binary(large & 0x111); cout << large << " == " << large << "? " << (large == large) << '\n'; cout << large << " != " << large << "? " << (large != large) << '\n'; cout << large << " < " << five << "? " << (large < five) << '\n'; cout << large << " <= " << five << "? " << (large <= five) << '\n'; cout << large << " > " << five << "? " << (large > five) << '\n'; cout << large << " >= " << five << "? " << (large >= five) << '\n'; large = 123456789; cout << large << ".exp(4) = "; cout << large.expc(4) << '\n'; cout << large << ".expModc(123, 169) = "; cout << large.expModc(123, 169) << '\n'; BigInt invmod(large.inverseModc(169)); cout << "large.inverseMod(169) = invmod = " << invmod << '\n'; cout << large << ".mulModc(invmod, 169): "; cout << large.mulModc(invmod, 169) << '\n'; cout << "as: (large * invmod) % 169: " << (large * invmod) % 169 << '\n'; cout << "Illustrating encryption using xor operations:\n"; string orig("This is the secret message"); cout << "original text: " << orig << '\n'; BigInt origNr; origNr = BigInt::setBigEndian(orig); BigInt randnr(BigInt::rand(origNr.size())); cout << "orig text in hex: " << hex << origNr << dec << '\n'; cout << "same nr of random nrs: " << hex << randnr << dec << '\n'; cout << hex; cout << "orig txt ^ random nrs: " << (origNr ^= randnr) << '\n'; cout << "orig txt ^ random nrs: " << (origNr ^= randnr) << dec << '\n'; cout << "retrieved text: "; char *txt = origNr.bigEndian(); cout.write(txt, origNr.sizeInBytes()) << '\n'; } catch(Errno const &err) { cout << err.why() << '\n'; return 1; } bobcat-3.19.01/bigint/opshlis.f0000644000175000017500000000011712223023055015200 0ustar frankfrankinline BigInt &BigInt::operator<<=(size_t nBits) { return lshift(nBits); } bobcat-3.19.01/bigint/maskbits.cc0000644000175000017500000000027312222576523015513 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::maskBits(size_t lowerNBits) { if (!BN_mask_bits(&d_bn, lowerNBits)) throw Exception() << "BigInt::maskBits failed"; return *this; } bobcat-3.19.01/bigint/randrange.cc0000644000175000017500000000035112222576523015634 0ustar frankfrank#include "bigint.ih" BigInt BigInt::randRange(BigInt const &max) { BigInt ret; if (BN_rand_range(&ret.d_bn, const_cast(&max.d_bn)) != 1) throw Exception() << "BigInt::randRange() failed"; return ret; } bobcat-3.19.01/bigint/checked3.cc0000644000175000017500000000041512222576523015345 0ustar frankfrank#include "bigint.ih" void BigInt::checked3(BIGNUM *div, BIGNUM *rem, BigInt const &rhs, char const *op) const { BNCTX ctx; if (BN_div(div, rem, &d_bn, &rhs.d_bn, ctx) != 1) throw Exception() << "BigInt " << op << " failed"; } bobcat-3.19.01/bigint/tildeint.cc0000644000175000017500000000016612222576523015513 0ustar frankfrank#include "bigint.ih" // neg = toggle + 1 -> toggle = neg - 1 BigInt &BigInt::tildeInt() { return --negate(); } bobcat-3.19.01/bigint/negate.cc0000644000175000017500000000016412222576523015140 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::negate() { BN_set_negative(&d_bn, not isNegative()); return *this; } bobcat-3.19.01/bigint/bitoperatororis.cc0000644000175000017500000000021712222576523017123 0ustar frankfrank#include "bigint.ih" BigInt::Bit &BigInt::Bit::operator|=(bool rhs) { d_bi.setBit(d_idx, rhs || d_bi.hasBit(d_idx)); return *this; } bobcat-3.19.01/bigint/nwords.f0000644000175000017500000000007612224007777015055 0ustar frankfrankinline size_t BigInt::nWords() const { return d_bn.top; } bobcat-3.19.01/bigint/divc.cc0000644000175000017500000000027112222576523014621 0ustar frankfrank#include "bigint.ih" BigInt BigInt::divc(BigInt *remainder, BigInt const &rhs) const { BigInt ret(*this); checked3(&ret.d_bn, &remainder->d_bn, rhs, "div"); return ret; } bobcat-3.19.01/bigint/inversemodc.cc0000644000175000017500000000022112222576523016205 0ustar frankfrank#include "bigint.ih" BigInt BigInt::inverseModc(BigInt const &mod) const { BigInt ret(*this); mod_inverse(&ret, mod); return ret; } bobcat-3.19.01/bigint/gcdc.cc0000644000175000017500000000020012222576523014564 0ustar frankfrank#include "bigint.ih" BigInt BigInt::gcdc(BigInt const &rhs) const { BigInt ret(*this); ret.gcd(rhs); return ret; } bobcat-3.19.01/bigint/bigendian.cc0000644000175000017500000000027312222576523015616 0ustar frankfrank#include "bigint.ih" char *BigInt::bigEndian() const { char *ret = new char[sizeInBytes()]; BN_bn2bin(&d_bn, reinterpret_cast(ret)); return ret; } bobcat-3.19.01/bigint/expmod.cc0000644000175000017500000000036612222576523015175 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::expMod(BigInt const &exponent, BigInt const &mod) { BNCTX ctx; if (BN_mod_exp(&d_bn, &d_bn, &exponent.d_bn, &mod.d_bn, ctx) == 0) throw Exception() << "BigInt sqr() failed"; return *this; } bobcat-3.19.01/bigint/isone.f0000644000175000017500000000010312223023055014627 0ustar frankfrankinline bool BigInt::isOne() const { return BN_is_one(&d_bn); } bobcat-3.19.01/bigint/opinsert.f0000644000175000017500000000015012223023055015357 0ustar frankfrankinline std::ostream &operator<<(std::ostream &out, BigInt const &bn) { return bn.insertInto(out); } bobcat-3.19.01/bigint/gcd.cc0000644000175000017500000000016512222576523014433 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::gcd(BigInt const &rhs) { checked4(BN_gcd, rhs, "gcd"); return *this; } bobcat-3.19.01/bigint/isqrtc.cc0000644000175000017500000000016012222576523015176 0ustar frankfrank#include "bigint.ih" BigInt BigInt::isqrtc() const { BigInt ret(*this); ret.isqrt(); return ret; } bobcat-3.19.01/bigint/opdec.f0000644000175000017500000000007712223023055014616 0ustar frankfrankinline BigInt &BigInt::operator--() { return *this -= 1; } bobcat-3.19.01/bigint/pseudorandrange.cc0000644000175000017500000000037412222576523017061 0ustar frankfrank#include "bigint.ih" BigInt BigInt::pseudoRandRange(BigInt const &max) { BigInt ret; if (BN_pseudo_rand_range(&ret.d_bn, const_cast(&max.d_bn)) != 1) throw Exception() << "BigInt::pseudoRandRange() failed"; return ret; } bobcat-3.19.01/bigint/isoctdigit.cc0000644000175000017500000000015512222576523016037 0ustar frankfrank#include "bigint.ih" namespace FBB { int isoctdigit(int ch) { return strchr("01234567", ch) != 0; } } bobcat-3.19.01/bigint/tildebits.cc0000644000175000017500000000054712222576523015665 0ustar frankfrank#include "bigint.ih" // toggles all bits and sign BigInt &BigInt::tildeBits() { size_t nBytes = sizeInBytes(); unsigned char buf[nBytes]; bool sign = isNegative(); BN_bn2bin(&d_bn, buf); for (size_t idx = nBytes; idx--; ) buf[idx] = ~buf[idx]; BN_bin2bn(buf, nBytes, &d_bn); setNegative(!sign); return *this; } bobcat-3.19.01/bigint/lshift2.cc0000644000175000017500000000027312222576523015251 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::lshift(size_t nBits) { if (!BN_lshift(&d_bn, &d_bn, nBits)) throw Exception() << "BigInt::lshift(size_t) failed"; return *this; } bobcat-3.19.01/bigint/opshris.f0000644000175000017500000000011712223023055015206 0ustar frankfrankinline BigInt &BigInt::operator>>=(size_t nBits) { return rshift(nBits); } bobcat-3.19.01/bigint/compare.f0000644000175000017500000000014112223023055015142 0ustar frankfrankinline int BigInt::compare(BigInt const &other) const { return BN_cmp(&d_bn, &other.d_bn); } bobcat-3.19.01/bigint/bigint6.cc0000644000175000017500000000021512222576523015234 0ustar frankfrank#include "bigint.ih" BigInt::BigInt(string const &bigEndian, bool negative) : BigInt(bigEndian.data(), bigEndian.length(), negative) {} bobcat-3.19.01/bigint/opgreater.f0000644000175000017500000000014212223023055015505 0ustar frankfrankinline bool operator>(BigInt const &lhs, BigInt const &rhs) { return lhs.compare(rhs) > 0; } bobcat-3.19.01/bigint/operatorxoris.cc0000644000175000017500000000147712222576523016625 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::operator^=(BigInt const &rhs) { setNegative(isNegative() ^ rhs.isNegative()); size_t nMin = min(sizeInBytes(), rhs.sizeInBytes()); size_t nMax = max(sizeInBytes(), rhs.sizeInBytes()); unsigned char small[nMin]; unsigned char large[nMax]; BIGNUM const *bSmall; BIGNUM const *bLarge; if (sizeInBytes() < rhs.sizeInBytes()) { bSmall = &d_bn; bLarge = &rhs.d_bn; } else { bLarge = &d_bn; bSmall = &rhs.d_bn; } BN_bn2bin(bSmall, small); BN_bn2bin(bLarge, large); unsigned char *largePtr = large + nMax - nMin; for (size_t idx = 0; idx != nMin; ++idx) // XOR bytes 0 to nMin largePtr[idx] ^= small[idx]; BN_bin2bn(large, nMax, &d_bn); return *this; } bobcat-3.19.01/bigint/lshiftc1.cc0000644000175000017500000000016412222576523015412 0ustar frankfrank#include "bigint.ih" BigInt BigInt::lshiftc() const { BigInt ret(*this); ret.lshift(); return ret; } bobcat-3.19.01/bigint/mulmod.f0000644000175000017500000000017512223023055015020 0ustar frankfrankinline BigInt &BigInt::mulMod(BigInt const &rhs, BigInt const &mod) { return checked2(BN_mod_mul, rhs, mod, "mulMod"); } bobcat-3.19.01/bigint/operatordivide.cc0000644000175000017500000000023212222576523016711 0ustar frankfrank#include "bigint.ih" namespace FBB { BigInt operator/(BigInt const &lhs, BigInt const &rhs) { BigInt tmp(lhs); tmp /= rhs; return tmp; } } bobcat-3.19.01/bigint/swap.cc0000644000175000017500000000012512222576523014644 0ustar frankfrank#include "bigint.ih" void BigInt::swap(BigInt &other) { fswap(*this, other); } bobcat-3.19.01/bigint/adddigit.cc0000644000175000017500000000067112222576523015451 0ustar frankfrank#include "bigint.ih" bool BigInt::addDigit(char ch, BigInt &ret, BigInt const &radix, int (*pConv)(int)) { if (not (*pConv)(static_cast(ch))) return true; // true means: character outside of expected range // which will end find_if. ret *= radix; ret += isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; return false; } bobcat-3.19.01/bigint/setbitc2.cc0000644000175000017500000000022612222576523015413 0ustar frankfrank#include "bigint.ih" BigInt BigInt::setBitc(size_t index, bool value) const { BigInt ret(*this); ret.setBit(index, value); return ret; } bobcat-3.19.01/bigint/iszero.f0000644000175000017500000000010512223023055015027 0ustar frankfrankinline bool BigInt::isZero() const { return BN_is_zero(&d_bn); } bobcat-3.19.01/bigint/operatormul.cc0000644000175000017500000000023212222576523016242 0ustar frankfrank#include "bigint.ih" namespace FBB { BigInt operator*(BigInt const &lhs, BigInt const &rhs) { BigInt tmp(lhs); tmp *= rhs; return tmp; } } bobcat-3.19.01/bigint/at.cc0000644000175000017500000000017112224015070014262 0ustar frankfrank#include "bigint.ih" BigInt::Word BigInt::at(size_t index) const { nWordsCheck(index); return d_bn.d[index]; } bobcat-3.19.01/bigint/bigint1.cc0000644000175000017500000000007712222576523015235 0ustar frankfrank#include "bigint.ih" BigInt::BigInt() { BN_init(&d_bn); } bobcat-3.19.01/bigint/bignum.f0000644000175000017500000000010112223023055014771 0ustar frankfrankinline BIGNUM const &BigInt::bignum() const { return d_bn; } bobcat-3.19.01/bigint/bitoperatorandis.cc0000644000175000017500000000021712222576523017245 0ustar frankfrank#include "bigint.ih" BigInt::Bit &BigInt::Bit::operator&=(bool rhs) { d_bi.setBit(d_idx, rhs && d_bi.hasBit(d_idx)); return *this; } bobcat-3.19.01/bigint/insertinto.cc0000644000175000017500000000150312222576523016071 0ustar frankfrank#include "bigint.ih" ostream &BigInt::insertInto(ostream &out) const { int flags = out.flags(); char *cp = ( flags & ios::hex ? BN_bn2hex : flags & ios::oct ? bn2oct : BN_bn2dec )(&d_bn); bool isNegative = (*cp == '-'); char *skipZeroes = cp + isNegative; while (*skipZeroes == '0') // cut off leading zeros ++skipZeroes; if ((flags & ios::oct) || *skipZeroes == 0) // if just 1 char or oct: --skipZeroes; // keep 1 '0' if (isNegative) *--skipZeroes = '-'; // restore the '-' out << skipZeroes; // insert the value if (flags & ios::oct) delete[] cp; else OPENSSL_free(cp); return out; } bobcat-3.19.01/bigint/tildeintc.cc0000644000175000017500000000016612222576523015656 0ustar frankfrank#include "bigint.ih" BigInt BigInt::tildeIntc() const { BigInt ret(*this); ret.tildeInt(); return ret; } bobcat-3.19.01/bigint/operatorinc.cc0000644000175000017500000000015712222576523016224 0ustar frankfrank#include "bigint.ih" BigInt BigInt::operator++(int) { BigInt tmp(*this); ++*this; return tmp; } bobcat-3.19.01/bigint/addmodc.cc0000644000175000017500000000023712222576523015271 0ustar frankfrank#include "bigint.ih" BigInt BigInt::addModc(BigInt const &rhs, BigInt const &mod) const { BigInt ret(*this); ret.addMod(rhs, mod); return ret; } bobcat-3.19.01/bigint/setbigendian.cc0000644000175000017500000000034212222576523016327 0ustar frankfrank#include "bigint.ih" BigInt BigInt::setBigEndian(std::string const &bytes) { BigInt tmp; BN_bin2bn(reinterpret_cast(bytes.data()), bytes.length(), &tmp.d_bn); return tmp; } bobcat-3.19.01/bigint/tildebitsc.cc0000644000175000017500000000017012222576523016020 0ustar frankfrank#include "bigint.ih" BigInt BigInt::tildeBitsc() const { BigInt ret(*this); ret.tildeBits(); return ret; } bobcat-3.19.01/bigint/sqrmod.f0000644000175000017500000000014512223023055015025 0ustar frankfrankinline BigInt &BigInt::sqrMod(BigInt const &mod) { return checked4(BN_mod_sqr, mod, "sqrMod"); } bobcat-3.19.01/bigint/operatorxor.cc0000644000175000017500000000024112222576523016255 0ustar frankfrank#include "bigint.ih" namespace FBB { BigInt operator^(BigInt const &lhs, BigInt const &rhs) { BigInt tmp(lhs); tmp ^= rhs; return tmp; } } // FBB bobcat-3.19.01/bigint/bitoperatorxoris.cc0000644000175000017500000000021612222576523017312 0ustar frankfrank#include "bigint.ih" BigInt::Bit &BigInt::Bit::operator^=(bool rhs) { d_bi.setBit(d_idx, rhs ^ d_bi.hasBit(d_idx)); return *this; } bobcat-3.19.01/bigint/operatorassign.cc0000644000175000017500000000020212222576523016726 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::operator=(BigInt const &other) { BigInt tmp(other); swap(tmp); return *this; } bobcat-3.19.01/bigint/lshiftc2.cc0000644000175000017500000000020512222576523015407 0ustar frankfrank#include "bigint.ih" BigInt BigInt::lshiftc(size_t nBits) const { BigInt ret(*this); ret.lshift(nBits); return ret; } bobcat-3.19.01/bigint/opinc.f0000644000175000017500000000007712223023055014634 0ustar frankfrankinline BigInt &BigInt::operator++() { return *this += 1; } bobcat-3.19.01/bigint/opindex.f0000644000175000017500000000013712223023055015167 0ustar frankfrankinline BigInt::Bit BigInt::operator[](size_t idx) { Bit bit(*this, idx); return bit; } bobcat-3.19.01/bigint/sqr.cc0000644000175000017500000000025712222576523014505 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::sqr() { BNCTX ctx; if (BN_sqr(&d_bn, &d_bn, ctx) != 1) throw Exception() << "BigInt sqr() failed"; return *this; } bobcat-3.19.01/bigint/operatormulis.cc0000644000175000017500000000031712222576523016602 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::operator*=(BigInt const &rhs) { BNCTX ctx; if (BN_mul(&d_bn, &d_bn, &rhs.d_bn, ctx) == 0) throw Exception() << "BigInt *= failed"; return *this; } bobcat-3.19.01/bigint/sizeinbytes.f0000644000175000017500000000011612223023055016066 0ustar frankfrankinline size_t BigInt::sizeInBytes() const { return BN_num_bytes(&d_bn); } bobcat-3.19.01/bigint/operatoror.cc0000644000175000017500000000023212222576523016065 0ustar frankfrank#include "bigint.ih" namespace FBB { BigInt operator|(BigInt const &lhs, BigInt const &rhs) { BigInt tmp(lhs); tmp |= rhs; return tmp; } } bobcat-3.19.01/bigint/operatororis.cc0000644000175000017500000000150112222576523016421 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::operator|=(BigInt const &rhs) { if (rhs.isNegative()) setNegative(true); size_t nMin = min(sizeInBytes(), rhs.sizeInBytes()); size_t nMax = max(sizeInBytes(), rhs.sizeInBytes()); unsigned char small[nMin]; unsigned char large[nMax]; BIGNUM const *bSmall; BIGNUM const *bLarge; if (sizeInBytes() < rhs.sizeInBytes()) { bSmall = &d_bn; bLarge = &rhs.d_bn; } else { bLarge = &d_bn; bSmall = &rhs.d_bn; } BN_bn2bin(bSmall, small); BN_bn2bin(bLarge, large); unsigned char *largePtr = large + nMax - nMin; for (size_t idx = 0; idx != nMin; ++idx) // OR bytes 0 to nMin largePtr[idx] |= small[idx]; BN_bin2bn(large, nMax, &d_bn); return *this; } bobcat-3.19.01/bigint/operatordivis.cc0000644000175000017500000000017612222576523016572 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::operator/=(BigInt const &rhs) { checked3(&d_bn, 0, rhs, "/="); return *this; } bobcat-3.19.01/bigint/bnctx.f0000644000175000017500000000006412223023055014636 0ustar frankfrankinline BNCTX::BNCTX() { d_ctx = BN_CTX_new(); } bobcat-3.19.01/bigint/inversemod.cc0000644000175000017500000000016612222576523016052 0ustar frankfrank#include "bigint.ih" BigInt &BigInt::inverseMod(BigInt const &mod) { mod_inverse(this, mod); return *this; } bobcat-3.19.01/bigint/mulmodc.cc0000644000175000017500000000023712222576523015336 0ustar frankfrank#include "bigint.ih" BigInt BigInt::mulModc(BigInt const &rhs, BigInt const &mod) const { BigInt ret(*this); ret.mulMod(rhs, mod); return ret; } bobcat-3.19.01/bigint/operatordec.cc0000644000175000017500000000015712222576523016206 0ustar frankfrank#include "bigint.ih" BigInt BigInt::operator--(int) { BigInt tmp(*this); --*this; return tmp; } bobcat-3.19.01/bigint/setword.cc0000644000175000017500000000020312224014061015340 0ustar frankfrank#include "bigint.ih" void BigInt::setWord(size_t index, BigInt::Word word) { nWordsCheck(index); d_bn.d[index] = word; } bobcat-3.19.01/bigint/maskbitsc.cc0000644000175000017500000000022212222576523015650 0ustar frankfrank#include "bigint.ih" BigInt BigInt::maskBitsc(size_t lowerNBits) const { BigInt ret(*this); ret.maskBits(lowerNBits); return ret; } bobcat-3.19.01/bigint/ucompare.f0000644000175000017500000000014312223023055015331 0ustar frankfrankinline int BigInt::uCompare(BigInt const &other) const { return BN_ucmp(&d_bn, &other.d_bn); } bobcat-3.19.01/binarysearch/0000755000175000017500000000000012223023055014547 5ustar frankfrankbobcat-3.19.01/binarysearch/binarysearch2.f0000644000175000017500000000101112223023055017443 0ustar frankfranktemplate Iterator binary_search(Iterator begin, Iterator end, Type const &value, Comparator comparator) { Iterator ret = end; while (begin != end) { Iterator mid = begin + (end - begin >> 1); if (comparator(value, *mid)) // left half end = mid; else if (comparator(*mid, value)) // right half begin = mid + 1; else return mid; } return ret; } bobcat-3.19.01/binarysearch/driver/0000755000175000017500000000000012222576540016055 5ustar frankfrankbobcat-3.19.01/binarysearch/driver/build0000755000175000017500000000004312222576540017077 0ustar frankfrank#!/bin/sh g++ -o driver driver.cc bobcat-3.19.01/binarysearch/driver/driver.cc0000644000175000017500000000250412222576540017660 0ustar frankfrank#include #include #include "../binarysearch" using namespace std; using namespace FBB; string words[] = { "eight", // alphabetically sorted number-names "five", "four", "nine", "one", "seven", "six", "ten", "three", "two" }; class Comparator { public: bool operator()(string const &left, string const &right) const; }; inline bool Comparator::operator()(string const &left, string const &right) const { return left < right; } bool compFun(string const &left, string const &right) { return left < right; } int main() { string *ret = binary_search(words, words + 10, "five"); if (ret != words + 10) cout << "five is at offset " << (ret - words) << endl; ret = binary_search(words, words + 10, "grandpa"); if (ret == words + 10) cout << "grandpa is not the name of a number\n"; ret = binary_search(words, words + 10, "five", Comparator()); if (ret != words + 10) cout << "five is at offset " << (ret - words) << endl; ret = binary_search(words, words + 10, "grandpa", compFun); // or use: Comparator() if (ret == words + 10) cout << "grandpa is not the name of a number\n"; return 0; } bobcat-3.19.01/binarysearch/binarysearch1.f0000644000175000017500000000065512223023055017457 0ustar frankfranktemplate Iterator binary_search(Iterator begin, Iterator end, Type const &value) { Iterator ret = end; while (begin != end) { Iterator mid = begin + (end - begin >> 1); if (value < *mid) // left half end = mid; else if (*mid < value) // right half begin = mid + 1; else return mid; } return ret; } bobcat-3.19.01/binarysearch/binarysearch0000644000175000017500000000040412223023055017142 0ustar frankfrank#ifndef INCLUDED_BOBCAT_BINARYSEARCH_ #define INCLUDED_BOBCAT_BINARYSEARCH_ namespace FBB { #include "binarysearch1.f" // Iterator begin, Iterator end, Type const &value #include "binarysearch2.f" // (... same ...), Comparator comparator } // FBB #endif bobcat-3.19.01/binops/0000755000175000017500000000000012223024752013374 5ustar frankfrankbobcat-3.19.01/binops/opdiv1.f0000644000175000017500000000016612223024752014750 0ustar frankfranktemplate inline Class operator/(Class &&lhs, Class const &rhs) { return std::move(lhs /= rhs); } bobcat-3.19.01/binops/opshr1.f0000644000175000017500000000017012223024752014755 0ustar frankfranktemplate inline Class operator>>(Class &&lhs, Class const &rhs) { return std::move(lhs >>= rhs); } bobcat-3.19.01/binops/binops0000644000175000017500000000260312223024752014612 0ustar frankfrank#ifndef INCLUDED_BOBCAT_BINOPS_ #define INCLUDED_BOBCAT_BINOPS_ // This header file requires the separate inclusion of // // // The templates in this file were not defined in the namespace FBB to enhance // their usability. If you want to declare them in a namespace of your own // include them in your namespace-block, like this: // namespace YOUR_NAMESPACE // { // #include // } #include "opadd1.f" // Class && + Class #include "opadd2.f" // LHS + RHS #include "opbitand1.f" // Class && & Class #include "opbitand2.f" // LHS & RHS #include "opbitor1.f" // Class && | Class #include "opbitor2.f" // LHS | RHS #include "opbitxor1.f" // Class && ^ Class #include "opbitxor2.f" // LHS ^ RHS #include "opdiv1.f" // Class && / Class #include "opdiv2.f" // LHS / RHS #include "opmod1.f" // Class && % Class #include "opmod2.f" // LHS % RHS #include "opshl1.f" // Class && << Class #include "opshl2.f" // LHS << RHS #include "opshr1.f" // Class && >> Class #include "opshr2.f" // LHS >> RHS #include "opsub1.f" // Class && - Class #include "opsub2.f" // LHS - RHS #include "optimes1.f" // Class && * Class #include "optimes2.f" // LHS * RHS #endif bobcat-3.19.01/binops/opbitor2.f0000644000175000017500000000040112223024752015276 0ustar frankfranktemplate inline typename FBB::Use::type operator|(LHS const &lhs, RHS const &rhs) { typename FBB::Use::type tmp(lhs); tmp |= rhs; return tmp; } bobcat-3.19.01/binops/opshl1.f0000644000175000017500000000017012223024752014747 0ustar frankfranktemplate inline Class operator<<(Class &&lhs, Class const &rhs) { return std::move(lhs <<= rhs); } bobcat-3.19.01/binops/opbitand1.f0000644000175000017500000000016612223024752015427 0ustar frankfranktemplate inline Class operator&(Class &&lhs, Class const &rhs) { return std::move(lhs &= rhs); } bobcat-3.19.01/binops/optimes2.f0000644000175000017500000000040112223024752015300 0ustar frankfranktemplate inline typename FBB::Use::type operator*(LHS const &lhs, RHS const &rhs) { typename FBB::Use::type tmp(lhs); tmp *= rhs; return tmp; } bobcat-3.19.01/binops/opsub2.f0000644000175000017500000000040112223024752014750 0ustar frankfranktemplate inline typename FBB::Use::type operator-(LHS const &lhs, RHS const &rhs) { typename FBB::Use::type tmp(lhs); tmp -= rhs; return tmp; } bobcat-3.19.01/binops/optimes1.f0000644000175000017500000000016612223024752015307 0ustar frankfranktemplate inline Class operator*(Class &&lhs, Class const &rhs) { return std::move(lhs *= rhs); } bobcat-3.19.01/binops/driver/0000755000175000017500000000000012222576524014677 5ustar frankfrankbobcat-3.19.01/binops/driver/build0000755000175000017500000000007312222576524015724 0ustar frankfrank#!/bin/bash g++ --std=c++0x -Wall -o driver driver.cc -s bobcat-3.19.01/binops/driver/driver.cc0000644000175000017500000000151212222576524016500 0ustar frankfrank#include #include #include "../../typetrait/typetrait" #include "../binops" class Demo { friend std::ostream &operator<<(std::ostream &out, Demo const &demo); int d_value; public: Demo(int value = 0) : d_value(value) {} Demo(Demo const &other) : d_value(other.d_value) { std::cout << "Demo CC called\n"; } Demo &operator+=(Demo const &rhs) { d_value += rhs.d_value; return *this; } }; std::ostream &operator<<(std::ostream &out, Demo const &demo) { return out << demo.d_value; } using namespace std; int main() { Demo four(4); Demo five(5); cout << four + five << '\n' << four + 5 << '\n' << 4 + five << '\n'; } bobcat-3.19.01/binops/opmod1.f0000644000175000017500000000016612223024752014745 0ustar frankfranktemplate inline Class operator%(Class &&lhs, Class const &rhs) { return std::move(lhs %= rhs); } bobcat-3.19.01/binops/opbitand2.f0000644000175000017500000000040112223024752015420 0ustar frankfranktemplate inline typename FBB::Use::type operator&(LHS const &lhs, RHS const &rhs) { typename FBB::Use::type tmp(lhs); tmp &= rhs; return tmp; } bobcat-3.19.01/binops/opbitxor1.f0000644000175000017500000000016612223024752015475 0ustar frankfranktemplate inline Class operator^(Class &&lhs, Class const &rhs) { return std::move(lhs ^= rhs); } bobcat-3.19.01/binops/opbitxor2.f0000644000175000017500000000040112223024752015466 0ustar frankfranktemplate inline typename FBB::Use::type operator^(LHS const &lhs, RHS const &rhs) { typename FBB::Use::type tmp(lhs); tmp ^= rhs; return tmp; } bobcat-3.19.01/binops/opadd2.f0000644000175000017500000000040112223024752014707 0ustar frankfranktemplate inline typename FBB::Use::type operator+(LHS const &lhs, RHS const &rhs) { typename FBB::Use::type tmp(lhs); tmp += rhs; return tmp; } bobcat-3.19.01/binops/opadd1.f0000644000175000017500000000016612223024752014716 0ustar frankfranktemplate inline Class operator+(Class &&lhs, Class const &rhs) { return std::move(lhs += rhs); } bobcat-3.19.01/binops/opdiv2.f0000644000175000017500000000040112223024752014741 0ustar frankfranktemplate inline typename FBB::Use::type operator/(LHS const &lhs, RHS const &rhs) { typename FBB::Use::type tmp(lhs); tmp /= rhs; return tmp; } bobcat-3.19.01/binops/opmod2.f0000644000175000017500000000040112223024752014736 0ustar frankfranktemplate inline typename FBB::Use::type operator%(LHS const &lhs, RHS const &rhs) { typename FBB::Use::type tmp(lhs); tmp %= rhs; return tmp; } bobcat-3.19.01/binops/opshr2.f0000644000175000017500000000040312223024752014755 0ustar frankfranktemplate inline typename FBB::Use::type operator>>(LHS const &lhs, RHS const &rhs) { typename FBB::Use::type tmp(lhs); tmp >>= rhs; return tmp; } bobcat-3.19.01/binops/opsub1.f0000644000175000017500000000016612223024752014757 0ustar frankfranktemplate inline Class operator-(Class &&lhs, Class const &rhs) { return std::move(lhs -= rhs); } bobcat-3.19.01/binops/opshl2.f0000644000175000017500000000040312223024752014747 0ustar frankfranktemplate inline typename FBB::Use::type operator<<(LHS const &lhs, RHS const &rhs) { typename FBB::Use::type tmp(lhs); tmp <<= rhs; return tmp; } bobcat-3.19.01/binops/opbitor1.f0000644000175000017500000000016612223024752015305 0ustar frankfranktemplate inline Class operator|(Class &&lhs, Class const &rhs) { return std::move(lhs |= rhs); } bobcat-3.19.01/build0000755000175000017500000000676212242427156013150 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/bobcat #include "INSTALL.im" #define ECHO_COMMANDS 1 #define LIBRARY "bobcat" #define DRYRUN "" //#define ONLYCLASSES // comment out if the additional library requiring classes should also // be compiled string g_cwd, // current WD g_file, // used to store the name of a file from a list g_copt, // compiler options g_cxx, // compiler used g_sources, // sources to be used g_version, // The library's version from the file VERSION g_tmplib, // Library compilation target g_tmphdr, // Class header target g_tmpbin, // Binary target g_lcgen, // bobcat lcgen program name g_lcgendefault, // default max size of the bobcat/lc structs g_sharedLibReq; // libraries required by the shared lib int g_nClasses; // number of classes/subdirectories list g_classes; // list of classes/directories, listed in CLASSES #include "icmake/run" #include "icmake/getenv" #include "icmake/clean" #include "icmake/addclasses"" #include "icmake/special" #include "icmake/man" #include "icmake/library" #include "icmake/libraries" #include "icmake/install" void main(int argc, list argv) { string option; string all; string strip; echo(ECHO_COMMANDS); g_cwd = chdir("."); g_tmplib = "tmp/lib/"; g_tmphdr = "tmp/" LIBRARY "/"; g_tmpbin = "tmp/bin/"; g_lcgen = "bobcatlcgen"; g_lcgendefault = " 10 "; // KEEP THE BLANKS setLocations(); // from INSTALL.im g_cxx = setOpt(CXX, "CXX"); g_copt = setOpt(CXXFLAGS, "CXXFLAGS"); option = element(1, argv); if (option == "clean" || option == "distclean") clean(); if (option == "libraries") { all = element(2, argv); if (all == "all") strip = element(3, argv); else strip = all; libraries("bobcat", all == "all", strip == "strip"); } if (option == "l") { system(P_NOCHECK, "tput clear"); libraries("bobcat", 1, 0); } if (option == "man") man(); if (option == "sf") { special(0, 0); exit(0); } if (option == "install") install(element(2, argv), element(3, argv)); printf("Usage: build what\n" "Where `what' is one of:\n" " clean - clean up remnants of previous compilations\n" " distclean - same as clean\n" " install - to install the software in the locations\n" " defined in the INSTALL.im file,\n" " optionally below (run-time package)\n" " and (development package)\n" " By default all is installed. To configure\n" " update setLocations() in INSTALL.im\n" " man - build the manual page (requires Yodl)\n" " libraries [all] [strip] - build the bobcat(-dev) libraries\n" " (optionally add optional classes,\n" " optionally strip the libraries)\n" " l - same as 'libraries all', but clearing the\n" " screen before starting the compilation\n" " sf - preliminaries required for SourceForge\n" ); exit(1); } bobcat-3.19.01/cgi/0000755000175000017500000000000012242431634012646 5ustar frankfrankbobcat-3.19.01/cgi/acceptall.cc0000644000175000017500000000025012222576524015110 0ustar frankfrank#include "cgi.ih" void CGIFSA::acceptAll() { while (d_stack.size()) { char top = d_stack.top(); setEscape(top); d_stack.pop(); } } bobcat-3.19.01/cgi/opinsert3.cc0000644000175000017500000000031112222576524015104 0ustar frankfrank#include "cgi.ih" CGI &CGI::operator<<(int ch) { if (!d_activated) { d_escape[static_cast(ch)] = d_escapeValue; d_escape['\\'] = true; } return *this; } bobcat-3.19.01/cgi/setparam.cc0000644000175000017500000000050112222576524014773 0ustar frankfrank#include "cgi.ih" void CGI::setParam() { if (d_activated || d_status.length() != 0) return; switch (d_method) { case GET: get(); break; case POST: post(); break; default: break; } report(); d_activated = true; } bobcat-3.19.01/cgi/isfile.cc0000644000175000017500000000064712222576524014445 0ustar frankfrank#include "cgi.ih" bool CGI::isFile(string const &line) try { d_contentDisposition.match(line); // match the content disposition try { d_contentFile.match(d_contentDisposition.beyond()); return true; } catch(...) { return false; // no file upload } } catch (...) { d_status = "Content-Disposition not recognized in: " + line; throw false; } bobcat-3.19.01/cgi/tokenidx.cc0000644000175000017500000000115612222576524015013 0ustar frankfrank#include "cgi.ih" size_t CGIFSA::tokenIdx() { size_t token = (this->*s_tokenizer[d_state])(); // get the next token vector::iterator ret = // look it up find_if( s_fsa[d_state].begin(), s_fsa[d_state].end(), [=](Transition const &transition) { return token == transition.token; } ); d_tokenIdx = ret - s_fsa[d_state].begin(); // determine the index if (d_tokenIdx == s_fsa[d_state].size()) --d_tokenIdx; return d_tokenIdx; // return it } bobcat-3.19.01/cgi/cgi2.cc0000644000175000017500000000121312222576524014004 0ustar frankfrank#include "cgi.ih" CGI::CGI(CGI &&tmp) : d_method(tmp.d_method), d_escapeValue(tmp.d_escapeValue), d_param( move(tmp.d_param) ), d_query( move(tmp.d_query) ), d_boundary( move(tmp.d_boundary) ), d_contentLength(tmp.d_contentLength), d_filePath( move(tmp.d_filePath) ), d_filePrefix( move(tmp.d_filePrefix) ), d_fileNr(tmp.d_fileNr), d_contentDisposition( move(tmp.d_contentDisposition) ), d_contentFile( move(tmp.d_contentFile) ), d_status( move(tmp.d_status) ), d_activated(tmp.d_activated), d_maxUploadSize(tmp.d_maxUploadSize) { memcpy(d_escape, tmp.d_escape, sizeof(d_escape)); } bobcat-3.19.01/cgi/typeof.cc0000644000175000017500000000040612222576524014471 0ustar frankfrank#include "cgi.ih" CGI::Boundary CGI::typeOf(string const &line) const { if (line.find(d_boundary) != 0) return NO_BOUNDARY; if (line.substr(d_boundary.length(), 2) == "--") // end of data return END_BOUNDARY; return BOUNDARY; } bobcat-3.19.01/cgi/cgi0000644000175000017500000001006512223023055013326 0ustar frankfrank#ifndef INCLUDED_BOBCAT_CGI_ #define INCLUDED_BOBCAT_CGI_ #include #include #include #include #include #include #include namespace FBB { class CGI { friend std::ostream &operator<<(std::ostream &out, CGI const &cgi); public: typedef std::unordered_map > MapStringVector; enum Method { UNDETERMINED, GET, POST }; enum Create { DONT_CREATE_PATH, CREATE_PATH }; private: enum Boundary // see multipartFormData() { NO_BOUNDARY, BOUNDARY, END_BOUNDARY }; Method d_method; bool d_escapeValue; bool d_escape[256]; // initially all d_defaultEscape MapStringVector d_param; std::string d_query; std::string d_boundary; // boundary of the multipart/form-data forms // empty if POST produces GET-like info on // stdin. unsigned long long d_contentLength; std::string d_filePath; // uploaded files are named std::string d_filePrefix; // d_filePath / d_filePrefix d_fileNr++ size_t d_fileNr; Pattern d_contentDisposition; Pattern d_contentFile; std::string d_status; bool d_activated; unsigned long long d_maxUploadSize; static std::vector s_empty; enum: size_t { s_uploadBlock = 8000, // upload.cc s_nTries = 100 }; public: explicit CGI(bool defaultEscape = true, char const *header = "Content-type: text/html", std::ostream &out = std::cout); CGI(CGI &&tmp); CGI &operator=(CGI const &rhs) = default; CGI &operator=(CGI &&tmp); CGI &operator<<(std::string const &set); CGI &operator<<(std::pair range); CGI &operator<<(int ch); void setFileDestination(std::string const &path, std::string const &prefix = "", Create create = CREATE_PATH); void setMaxUploadSize(size_t maxUploadSize, int unit = 'M'); void report() const; // also called by param() // accessors: char const *operator[](std::string const &key) const; // opindex.f unsigned long long maxUploadSize() const; // .f Method method() const; // .f std::string const &query() const; // .f // empty with multipart/form-data std::vector const ¶m(std::string const &variable); MapStringVector::const_iterator begin(); // .f MapStringVector::const_iterator end(); // .f std::string param1(std::string const &variable); // static members: // unpercent also does the '+' to ' ' // conversion static std::string unPercent(std::string const &text); static std::string dos2unix(std::string const &text); CGI(CGI const &&tmp); // Deprecated CGI &operator=(CGI const &&tmp); // Deprecated private: void setQuery(); void get(); void post(); void addParam(std::string const ¶m); void init(bool &target); std::string escape(std::string const &text); void next(std::string *line); void multipartFormData(); Boundary typeOf(std::string const &line) const; bool isFile(std::string const &line); void readPart(std::string *line); void setMethod(); void setParam(); void upload(std::string *line); }; #include "opindex.f" #include "query.f" #include "method.f" #include "begin.f" #include "end.f" } // namespace #endif bobcat-3.19.01/cgi/readpart.cc0000644000175000017500000000076412222576524014774 0ustar frankfrank#include "cgi.ih" void CGI::readPart(string *line) { next(line); // empty line following Content-Disposition while (true) { next(line); // either a boundary or a field value if (typeOf(*line) != NO_BOUNDARY) // it's a boundary break; // (i.e., NOT no boundary) // otherwise it's a field value d_param[d_contentDisposition[1]].push_back(escape(*line)); } } bobcat-3.19.01/cgi/cgi1.cc0000644000175000017500000000140412222576524014005 0ustar frankfrank#include "cgi.ih" CGI::CGI(bool defaultEscape, char const *header, std::ostream &out) : d_method(UNDETERMINED), d_escapeValue(defaultEscape), d_contentLength(0), d_filePath("/tmp/"), d_fileNr(1), d_contentDisposition("^Content-Disposition: form-data; name=\"([^\"]+)\""), d_contentFile("; filename=\"([^\"]+)\""), d_activated(false), d_maxUploadSize(100ULL * 1024 * 1024) { for (auto &target: ranger(d_escape, sizeof(d_escape) / sizeof(bool))) target = d_escapeValue; d_escapeValue = !d_escapeValue; // all changes will now change the // default setMethod(); if (d_status.length() == 0) setQuery(); if (header) out << header << "\r\n\r\n"; } bobcat-3.19.01/cgi/maxuploadsize.f0000644000175000017500000000012512223023055015671 0ustar frankfrankinline unsigned long long CGI::maxUploadSize() const { return d_maxUploadSize; } bobcat-3.19.01/cgi/method.f0000644000175000017500000000010012223023055014255 0ustar frankfrankinline CGI::Method CGI::method() const { return d_method; } bobcat-3.19.01/cgi/opinsert0.cc0000644000175000017500000000054212222576524015107 0ustar frankfrank#include "cgi.ih" std::ostream &FBB::operator<<(std::ostream &out, CGI const &cgi) { for (int idx = 0; idx < 256; ++idx) { if (cgi.d_escape[idx]) { if (isprint(idx)) out << "'" << static_cast(idx) << "'\n"; else out << idx << endl; } } return out; } bobcat-3.19.01/cgi/setescape.f0000644000175000017500000000011712223023055014761 0ustar frankfrankinline void CGIFSA::setEscape(size_t idx) { d_escape[idx] = d_setEscape; } bobcat-3.19.01/cgi/chartoken.cc0000644000175000017500000000024612222576524015143 0ustar frankfrank#include "cgi.ih" size_t CGIFSA::charToken() { char c; if (!d_in.get(c)) throw END; d_buffer = c; return static_cast(c); } bobcat-3.19.01/cgi/query.f0000644000175000017500000000010512223023055014147 0ustar frankfrankinline std::string const &CGI::query() const { return d_query; } bobcat-3.19.01/cgi/setmaxuploadsize.cc0000644000175000017500000000104012222576524016557 0ustar frankfrank#include "cgi.ih" void CGI::setMaxUploadSize(size_t maxUploadSize, int unit) { unsigned long long newSize = maxUploadSize; switch (unit) { case 'G': case 'g': newSize <<= 10; // FALLING THROUGH case 'M': case 'm': newSize <<= 10; // FALLING THROUGH case 'K': case 'k': newSize <<= 10; // FALLING THROUGH default: d_maxUploadSize = newSize; break; } } bobcat-3.19.01/cgi/iscgi.f0000644000175000017500000000012012223023055014075 0ustar frankfrankinline int CGIFSA::iscgi(int ch) { return s_cgi.find(ch) != string::npos; } bobcat-3.19.01/cgi/operatorassign2.cc0000644000175000017500000000017012222576524016303 0ustar frankfrank#include "cgi.ih" CGI &CGI::operator=(CGI const &&tmp) { fswap(*this, const_cast(tmp)); return *this; } bobcat-3.19.01/cgi/get.cc0000644000175000017500000000027012222576524013741 0ustar frankfrank#include "cgi.ih" void CGI::get() { vector words; String::split(&words, d_query, "&"); // split the q-string for (auto &word: words) addParam(word); } bobcat-3.19.01/cgi/last.f0000644000175000017500000000011412223023055013745 0ustar frankfrankinline std::string Cidr::last() const { return binary2dotted(d_last); } bobcat-3.19.01/cgi/run.cc0000644000175000017500000000104512222576524013767 0ustar frankfrank#include "cgi.ih" // Characters are retrieved from d_in by the tokenizer. They are stored on // the stack by the tokenizers, and retrieved from the stack by the // action functions. All characters are interpreted as unsigned chars, and // pushed as size_t values void CGIFSA::run() try { d_state = START; while (true) // throws exception after processing all chars { (this->*s_fsa[d_state][tokenIdx()].action)(); d_state = s_fsa[d_state][d_tokenIdx].next; } } catch(Token end) { acceptAll(); } bobcat-3.19.01/cgi/param1.cc0000644000175000017500000000030312222576524014340 0ustar frankfrank#include "cgi.ih" std::string CGI::param1(std::string const &variable) { auto &vect = param(variable); string ret; if (not vect.empty()) ret = vect[0]; return ret; } bobcat-3.19.01/cgi/accept.cc0000644000175000017500000000035212222576524014422 0ustar frankfrank#include "cgi.ih" void CGIFSA::accept() { for (auto iter = d_buffer.rbegin(), end = d_buffer.rend(); iter != end; ++iter) d_stack.push(*iter); acceptAll(); d_stack.push(*d_buffer.rbegin()); } bobcat-3.19.01/cgi/dos2unix.cc0000644000175000017500000000041612222576524014737 0ustar frankfrank#include "cgi.ih" string CGI::dos2unix(string const &text) { string ret(text); string::size_type pos = 0; while (true) { pos = ret.find("\r\n", pos); if (pos == string::npos) return ret; ret.erase(pos, 1); } } bobcat-3.19.01/cgi/upload.cc0000644000175000017500000000715612222576524014460 0ustar frankfrank#include "cgi.ih" namespace { char const content_Type[] = "Content-Type: "; } void CGI::upload(string *line) { next(line); // Content-Type if (line->find(content_Type) != 0) { d_status = "Content-Type not found for file-field " + d_contentDisposition[1]; throw false; } string contentType = line->substr(sizeof(content_Type) - 1); string destName; // try s_nTries times to find an available // file for (size_t end = d_fileNr + s_nTries; d_fileNr < end; ++d_fileNr) { destName = d_filePath + d_filePrefix + X2a(d_fileNr).str(); if (!Stat(destName)) // path does not exist break; } ofstream dest(destName.c_str()); if (!dest) { d_status = "Can't open a file to write an uploaded file"; throw false; } string previous; auto_ptr buffer(new char[s_uploadBlock]); next(line); // skip the blank line following the // content-type unsigned long long uploadSize = 0; while (true) { cin.getline(buffer.get(), s_uploadBlock); size_t nRead = cin.gcount(); // may include the \n, but the \n is // then stored as 0, since it is // removed from the input and an // \0 is appended to the read line if (!nRead) // none read: shouldn't happen { d_status = "multipart/form-data: no end-boundary found"; throw false; } if (cin.fail()) // on fail() no \n was encountered cin.clear(); else // no fail: change the \0 into \n (buffer.get())[nRead - 1] = '\n'; // the line that was read contains \r\n characters, so a boundary // can only be encountered if nRead exceeds the boundary length // if so, and the buffer's boundary length characters are equal to the // boundary then a boundary was found. // If the boundary is found, then the previously captured line ends in // a \r\n, which does not belong to the uploaded file but is added by // the browser's form-handling software which is therefore not // included in the uploaded file (hence `- 2', below). Then, the // boundary is copied to the line parameter and the function returns. if ( nRead > d_boundary.length() && d_boundary.compare(0, d_boundary.length(), buffer.get(), d_boundary.length()) == 0 ) { uploadSize += previous.length() - 2; if (uploadSize <= d_maxUploadSize) dest.write(previous.c_str(), previous.length() - 2); line->assign(buffer.get(), nRead); break; } if (uploadSize <= d_maxUploadSize) { uploadSize += previous.length(); dest.write(previous.c_str(), previous.length()); previous.assign(buffer.get(), nRead); } } // store the info about this file into d_param vector ¶m = d_param[d_contentDisposition[1]]; param.push_back(escape(destName)); param.push_back(escape(d_contentFile[1])); param.push_back(escape(contentType)); param.push_back(uploadSize <= d_maxUploadSize ? "OK" : "truncated"); } bobcat-3.19.01/cgi/wordtoken.cc0000644000175000017500000000155112222576524015201 0ustar frankfrank#include "cgi.ih" size_t CGIFSA::wordToken() { d_buffer.clear(); while (islower(d_in.peek())) // read all lowercase chars d_buffer += d_in.get(); if (!d_buffer.size()) // if none read, return the next char return charToken(); // look for a character class name PairCPPFunP const *ret = find_if( s_charClass, s_charClassEnd, [&](PairCPPFunP const &cClass) { return d_buffer == cClass.first; } ); if (ret == s_charClassEnd) // no character class found return static_cast(*d_buffer.rbegin()); d_setIdx = ret - s_charClass; // charclass found return SET; // return `set found' } bobcat-3.19.01/cgi/address.f0000644000175000017500000000011212223023055014425 0ustar frankfrankinline std::string const &Cidr::address() const { return d_matched; } bobcat-3.19.01/cgi/multipartformdata.cc0000644000175000017500000000164612222576524016731 0ustar frankfrank#include "cgi.ih" void CGI::multipartFormData() try { string line; next(&line); // enter while with the next // available line while (true) { switch (typeOf(line)) // handle the line-type { case END_BOUNDARY: return; default: // no boundary, try the next next(&line); continue; case BOUNDARY: next(&line); // line beyound the boundary if (isFile(line)) upload(&line); // upload a file else readPart(&line); // handle a plain part break; // upload() and readPart() return the next line to process } } } catch (...) {} bobcat-3.19.01/cgi/setfsa.cc0000644000175000017500000000050412222576524014447 0ustar frankfrank#include "cgi.ih" void CGIFSA::setFsa(Record const &record) { Transition transition = {record.token, record.action, record.next}; s_fsa[record.current].push_back(transition); if (record.token == DEFAULT) // default contains ptr to tokenizer s_tokenizer[record.current] = record.tokenizer; } bobcat-3.19.01/cgi/push.cc0000644000175000017500000000015412222576524014142 0ustar frankfrank#include "cgi.ih" void CGIFSA::push() { for (auto &element: d_buffer) d_stack.push(element); } bobcat-3.19.01/cgi/cgifsa.cc0000644000175000017500000000044712222576524014424 0ustar frankfrank#include "cgi.ih" CGIFSA::CGIFSA(bool *escape, std::istream &in, bool setEscape) : d_escape(escape), d_setEscape(setEscape), d_state(START), d_in(in) { if (!s_installed) { std::for_each(s_fsaRawData, s_fsaRawDataEnd, setFsa); s_installed = true; } } bobcat-3.19.01/cgi/begin.f0000644000175000017500000000015112223023055014067 0ustar frankfrankinline CGI::MapStringVector::const_iterator CGI::begin() { setParam(); return d_param.begin(); } bobcat-3.19.01/cgi/unpercent.cc0000644000175000017500000000160012222576524015163 0ustar frankfrank#include "cgi.ih" std::string CGI::unPercent(std::string const &text) { string ret(text); string::size_type pos = 0; string sub; char replacement[2] = {0, 0}; while (true) { pos = ret.find_first_of("+%", pos); if (pos == string::npos) // none found break; if (ret[pos] == '+') // convert '+' ret[pos] = ' '; // // viable % found else if ((sub = ret.substr(pos + 1, 2)).length() == 2) { istringstream convert(sub); size_t value; if (convert >> hex >> value) // successfully converted { replacement[0] = value; ret.replace(pos, 3, replacement); } } ++pos; // next char } return ret; } bobcat-3.19.01/cgi/driver/0000755000175000017500000000000012222576524014147 5ustar frankfrankbobcat-3.19.01/cgi/driver/usage.cc0000644000175000017500000000222512222576524015563 0ustar frankfrank// usage.cc #include "main.ih" namespace { Pattern pattern("([^=]*)=(.*)"); } void usage(std::string const &progname) { cout << "\n" << progname << " by " << Icmbuild::author << "\n" << progname << " V" << Icmbuild::version << " " << Icmbuild::year << "\n" "\n" "Usage: " << progname << " [options] arg to-escape < arg.cin\n" "Where:\n" " [options] - optional arguments (short options between parentheses):\n" " -e - show the environment variables that were set\n" " -m[bkmg] - max uploadsize to use\n" " -h - provide this help\n" " -v - show version information and terminate\n" " arg - file defining envvars\n" " (see, e.g., `get' and `post1')\n" " to-escape - RE defining characters to escape.\n" " (e.g., '[:cgi:]')\n" " < arg.cin - file to read, simulating form-output\n" " (e.g., post1.cin)\n" " For the 'get' method the input redirection is not used/required\n" "\n"; } bobcat-3.19.01/cgi/driver/post10000644000175000017500000000036012222576524015137 0ustar frankfrankINFO=This is an abbreviated set of environment variables CONTENT_TYPE=application/x-www-form-urlencoded CONTENT_LENGTH=182 SERVER_ADMIN=f.b.brokken@rug.nl GATEWAY_INTERFACE=CGI/1.1 SERVER_PROTOCOL=HTTP/1.1 REQUEST_METHOD=POST QUERY_STRING= bobcat-3.19.01/cgi/driver/get0000644000175000017500000000032112222576524014645 0ustar frankfrankINFO=This is an abbreviated set of environment variables SERVER_ADMIN=f.b.brokken@rug.nl GATEWAY_INTERFACE=CGI/1.1 SERVER_PROTOCOL=HTTP/1.1 REQUEST_METHOD=GET QUERY_STRING=hidden=hidval&submit=Submit+%20Query bobcat-3.19.01/cgi/driver/build0000755000175000017500000000200712222576524015173 0ustar frankfrank#!/bin/bash rm -f driver case $1 in (tmp) for x in *.cc do NAME=`echo $x | sed 's/\..*//'` if [ ! -s ${NAME}.o -o ${NAME}.cc -nt ${NAME}.o ] then echo "g++ -c $x" g++ --std=c++0x -I../../tmp -o ${NAME}.o -c $x || exit 1 fi done g++ --std=c++0x -o driver *.o -L../../tmp/lib -lbobcat ;; (lib) for x in *.cc do NAME=`echo $x | sed 's/\..*//'` if [ ! -s ${NAME}.o -o ${NAME}.cc -nt ${NAME}.o ] then echo "g++ -c $x" g++ --std=c++0x -o ${NAME}.o -c $x || exit 1 fi done g++ -o driver *.o -lbobcat ;; (*) echo " Usage: build tmp - build the driver using the shared library created in ../../tmp/lib build lib - build the driver using the shared bobcat library installed in the standard location for shared libs " exit 1 ;; esac bobcat-3.19.01/cgi/driver/version.cc0000644000175000017500000000031412222576524016141 0ustar frankfrank// version.cc #include "main.ih" namespace Icmbuild { char version[] = "0.00"; char year[] = "2007"; char author[] = "Frank B. Brokken (f.b.brokken@rug.nl)"; } bobcat-3.19.01/cgi/driver/driver.cc0000644000175000017500000000350512222576524015754 0ustar frankfrank#include "main.ih" void showParam(CGI::MapStringVector::value_type const &mapValue) { cout << "Param: " << mapValue.first << '\n'; for (auto &str: mapValue.second) cout << " " << CGI::dos2unix(str) << "\n" " "; cout << '\n'; } int main(int argc, char **argv) try { Arg &arg = Arg::initialize("evhm:", argc, argv); // usage and version are in the source archive in .../cgi/driver // arg.versionHelp(usage, version, 2); ifstream in(arg[0]); string line; while (getline(in, line)) { size_t pos = line.find('='); if (pos == string::npos) continue; // set environment vars simulating // a GET form if (setenv(line.substr(0, pos).c_str(), line.substr(pos + 1).c_str(), true) == 0) { if (arg.option('e')) cout << line.substr(0, pos).c_str() << '=' << line.substr(pos + 1).c_str() << '\n'; } else cout << "FAILED: setenv " << line << '\n'; } CGI cgi(false); // chars are not escaped cgi << arg[1]; if (arg.option(&line, 'm')) cgi.setMaxUploadSize(A2x(line), *line.rbegin()); cout << "Max upload size (b): " << cgi.maxUploadSize() << '\n'; CGI::Method method = cgi.method(); cout << "To escape:\n" << cgi << "\n" "Method: " << (method == CGI::GET ? "GET" : "POST") << '\n'; cout << "Query string: " << cgi.query() << '\n'; cout << "Submit string: `" << cgi.param1("submit") << "'\n"; for (auto &mapElement: cgi) showParam(mapElement); cout << "END OF PROGRAM\n"; } catch (exception const &err) { cout << err.what() << '\n'; return 1; } catch (...) { return 1; } bobcat-3.19.01/cgi/driver/main.ih0000644000175000017500000000057412222576524015423 0ustar frankfrank#include #include #include #include #include #include #include #include namespace Icmbuild { extern char version[]; extern char year[]; extern char author[]; }; void usage(std::string const &progname); using namespace std; using namespace FBB; using namespace Icmbuild; bobcat-3.19.01/cgi/driver/post20000644000175000017500000000044512222576524015144 0ustar frankfrankINFO=This is an abbreviated set of environment variables CONTENT_TYPE=multipart/form-data; boundary=---------------------------8463851424774285061082711556 CONTENT_LENGTH=1223 SERVER_ADMIN=f.b.brokken@rug.nl GATEWAY_INTERFACE=CGI/1.1 SERVER_PROTOCOL=HTTP/1.1 REQUEST_METHOD=POST QUERY_STRING= bobcat-3.19.01/cgi/driver/post1.cin0000644000175000017500000000026712222576524015715 0ustar frankfrankhidden=hidval&text=text+input&password=&c1=one&radio=1§ions=FAQ+Archives§ions=Tools&textarea=Enter+your+text+here%0D%0AAnd+over+multitple+rows+is+OK%0D%0A&submit=Submit+Query bobcat-3.19.01/cgi/driver/post2.cin0000644000175000017500000000231012222576524015705 0ustar frankfrank-----------------------------8463851424774285061082711556 Content-Disposition: form-data; name="hidden" hidval -----------------------------8463851424774285061082711556 Content-Disposition: form-data; name="text" some text -----------------------------8463851424774285061082711556 Content-Disposition: form-data; name="password" -----------------------------8463851424774285061082711556 Content-Disposition: form-data; name="c1" one -----------------------------8463851424774285061082711556 Content-Disposition: form-data; name="c1" three -----------------------------8463851424774285061082711556 Content-Disposition: form-data; name="radio" 1 -----------------------------8463851424774285061082711556 Content-Disposition: form-data; name="file"; filename="demo.pim" Content-Type: application/octet-stream #demo.im string a = "a/*" ; -----------------------------8463851424774285061082711556 Content-Disposition: form-data; name="textarea" Enter your text here And over multitple rows is OK -----------------------------8463851424774285061082711556 Content-Disposition: form-data; name="submit" Submit Query -----------------------------8463851424774285061082711556-- bobcat-3.19.01/cgi/setquery.cc0000644000175000017500000000116212222576524015044 0ustar frankfrank#include "cgi.ih" void CGI::setQuery() { switch (d_method) { case GET: if (char const *cp = (*this)["QUERY_STRING"]) d_query = cp; break; case POST: if (d_boundary.length() == 0) { auto_ptr cp(new char[d_contentLength]); if (!cin.read(cp.get(), d_contentLength)) d_status = "invalid CONTENT_LENGTH in POSTed form"; else d_query.assign(cp.get(), d_contentLength); } break; default: break; } } bobcat-3.19.01/cgi/opinsert1.cc0000644000175000017500000000040212222576524015103 0ustar frankfrank#include "cgi.ih" CGI &CGI::operator<<(string const &accept) { if (!d_activated) { istringstream in(accept); CGIFSA fsa(d_escape, in, d_escapeValue); fsa.run(); d_escape['\\'] = true; } return *this; } bobcat-3.19.01/cgi/next.cc0000644000175000017500000000024512222576524014142 0ustar frankfrank#include "cgi.ih" void CGI::next(string *line) { if (!getline(cin, *line)) { d_status = "Invalid multipart/form-data"; throw false; } } bobcat-3.19.01/cgi/setfiledestination.cc0000644000175000017500000000176412222576524017070 0ustar frankfrank#include "cgi.ih" void CGI::setFileDestination(std::string const &path, std::string const &prefix, Create create) { d_filePath = path; if (*d_filePath.rbegin() != '/') d_filePath += "/"; Stat destPath(d_filePath); if (!destPath.isType(Stat::DIRECTORY) && create == CREATE_PATH) { string::size_type pos = 0; while (true) { pos = path.find('/', pos); if ( pos == string::npos || mkdir(path.substr(0, pos).c_str(), 0750) ) break; ++pos; // skip the directory separator } } if (!destPath.isType(Stat::DIRECTORY)) throw Exception(1) << "FBB::CGI: can't create file destination " "directory " << destPath.path(); d_filePrefix = prefix; } bobcat-3.19.01/cgi/post.cc0000644000175000017500000000042612222576524014152 0ustar frankfrank#include "cgi.ih" void CGI::post() { if (!d_boundary.length()) // POSTed forms not using multipart/form-data { get(); // offer GET-like data via cin return; } multipartFormData(); // process the multipart/form-data } bobcat-3.19.01/cgi/end.f0000644000175000017500000000014512223023055013554 0ustar frankfrankinline CGI::MapStringVector::const_iterator CGI::end() { setParam(); return d_param.end(); } bobcat-3.19.01/cgi/escape.cc0000644000175000017500000000037612222576524014431 0ustar frankfrank#include "cgi.ih" string CGI::escape(string const &text) { string ret = text; for (size_t idx = ret.length(); idx--; ) { if (d_escape[static_cast(ret[idx])]) ret.insert(idx, "\\"); } return ret; } bobcat-3.19.01/cgi/addparam.cc0000644000175000017500000000036512222576524014740 0ustar frankfrank#include "cgi.ih" void CGI::addParam(string const ¶m) try { static Pattern pattern("([^=]*)=(.*)"); pattern.match(param); d_param[pattern[1]].push_back(escape(unPercent(pattern[2]))); } catch (std::exception const &exc) {} bobcat-3.19.01/cgi/first.f0000644000175000017500000000012412223023055014132 0ustar frankfrankinline std::string Cidr::first() const { return binary2dotted(d_iter->first); } bobcat-3.19.01/cgi/cgidata.cc0000644000175000017500000000655512222576524014572 0ustar frankfrank#include "cgi.ih" vector CGI::s_empty; bool CGIFSA::s_installed(false); vector CGIFSA::s_fsa[N_STATES_]; size_t (CGIFSA::*CGIFSA::s_tokenizer[N_STATES_])(); // a buffer is filled with the read character(s). push will push them // L to R onto the charstack // accept will pop all characters and accept them, except for the last // char, that is pushed CGIFSA::Record const CGIFSA::s_fsaRawData[] = { // -------------------------------------------------------------------- // cur. state token action next state tokenizer // -------------------------------------------------------------------- {START, '[', &CGIFSA::push, OPENBRACKET, 0}, {START, DEFAULT, &CGIFSA::push, CHECKSET, &CGIFSA::charToken}, {CHECKSET, '-', &CGIFSA::push, DEFINESET, 0}, {CHECKSET, '[', &CGIFSA::accept, OPENBRACKET, 0}, {CHECKSET, DEFAULT, &CGIFSA::accept, CHECKSET, &CGIFSA::charToken}, {DEFINESET, DEFAULT, &CGIFSA::charRange, START, &CGIFSA::charToken}, {OPENBRACKET, '-', &CGIFSA::push, DEFINESET, 0}, {OPENBRACKET, '[', &CGIFSA::accept, OPENBRACKET, 0}, {OPENBRACKET, ':', &CGIFSA::push, LEFTCOLON, 0}, {OPENBRACKET, DEFAULT, &CGIFSA::accept, CHECKSET, &CGIFSA::charToken}, {LEFTCOLON, SET, &CGIFSA::push, SETNAME, 0}, {LEFTCOLON, '-', &CGIFSA::push, DEFINESET, 0}, {LEFTCOLON, DEFAULT, &CGIFSA::accept, CHECKSET, &CGIFSA::wordToken}, {SETNAME, ':', &CGIFSA::push, RIGHTCOLON, 0}, {SETNAME, DEFAULT, &CGIFSA::accept, CHECKSET, &CGIFSA::charToken}, {RIGHTCOLON, ']', &CGIFSA::charClass, START, 0}, {RIGHTCOLON, '-', &CGIFSA::push, DEFINESET, 0}, {RIGHTCOLON, DEFAULT, &CGIFSA::accept, CHECKSET, &CGIFSA::charToken}, // -------------------------------------------------------------------- }; CGIFSA::Record const *const CGIFSA::s_fsaRawDataEnd = CGIFSA::s_fsaRawData + sizeof(CGIFSA::s_fsaRawData) / sizeof(CGIFSA::Record); PairCPPFunP const CGIFSA::s_charClass[] = { PairCPPFunP("alnum", &isalpha), PairCPPFunP("alpha", &isalpha), PairCPPFunP("cntrl", &iscntrl), PairCPPFunP("digit", &isdigit), PairCPPFunP("graph", &isgraph), PairCPPFunP("lower", &islower), PairCPPFunP("print", &isprint), PairCPPFunP("punct", &ispunct), PairCPPFunP("space", &isspace), PairCPPFunP("upper", &isupper), PairCPPFunP("xdigit", &isxdigit), PairCPPFunP("cgi", &iscgi), // extension to std char classes }; string CGIFSA::s_cgi("\"'`;\\"); PairCPPFunP const *const CGIFSA::s_charClassEnd = CGIFSA::s_charClass + sizeof(CGIFSA::s_charClass) / sizeof(PairCPPFunP); char const *CGIFSA::s_stateName[] = // change when enum State changes { "START", "CHECKSET", "DEFINESET", "OPENBRACKET", "LEFTCOLON", "SETNAME", "RIGHTCOLON", "STOP", }; bobcat-3.19.01/cgi/param.cc0000644000175000017500000000036412222576524014266 0ustar frankfrank#include "cgi.ih" std::vector const &CGI::param(std::string const &variable) { setParam(); MapStringVector::const_iterator iter = d_param.find(variable); return iter == d_param.end() ? s_empty : iter->second; } bobcat-3.19.01/cgi/mask.f0000644000175000017500000000011212223023055013733 0ustar frankfrankinline std::string Cidr::mask() const { return X2a(d_iter->second); } bobcat-3.19.01/cgi/cgi.ih0000644000175000017500000000441612223023055013730 0ustar frankfrank#include "cgi" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace FBB; namespace FBB { typedef pair PairCPPFunP; class CGIFSA { enum Token { DEFAULT = 256, SET, END, }; enum State // change data.cc s_stateName when this changes { START, CHECKSET, DEFINESET, OPENBRACKET, LEFTCOLON, SETNAME, RIGHTCOLON, N_STATES_, STOP = N_STATES_, }; struct Record { State current; size_t token; void (CGIFSA::*action)(); State next; size_t (CGIFSA::*tokenizer)(); }; stack d_stack; bool *d_escape; bool d_setEscape; State d_state; size_t d_tokenIdx; string d_buffer; size_t d_setIdx; istream &d_in; struct Transition { size_t token; void (CGIFSA::*action)(); State next; }; static vector s_fsa[]; static size_t (CGIFSA::*s_tokenizer[])(); static Record const s_fsaRawData[]; static Record const *const s_fsaRawDataEnd; static PairCPPFunP const s_charClass[]; static PairCPPFunP const *const s_charClassEnd; static bool s_installed; static char const *s_stateName[]; static string s_cgi; public: CGIFSA(bool *escape, istream &in = cin, bool setEscape = false); void run(); private: void push(); void accept(); void charRange(); void charClass(); void acceptAll(); // all elements on the stack size_t tokenIdx(); void setEscape(size_t idx); // .i size_t charToken(); size_t wordToken(); static void setFsa(Record const &record); static int iscgi(int ch); // .i }; #include "iscgi.f" #include "setescape.f" } // namespace bobcat-3.19.01/cgi/report.cc0000644000175000017500000000032612222576524014477 0ustar frankfrank#include "cgi.ih" void CGI::report() const { if (d_status.length() == 0) return; cout << "FBB::CGI: " << d_status << endl; throw Exception(1) << "FBB::CGI: Error(s) in uploaded form data"; } bobcat-3.19.01/cgi/charclass.cc0000644000175000017500000000060012222576524015122 0ustar frankfrank#include "cgi.ih" void CGIFSA::charClass() // saw: [ : charclass : ] { while (true) { char c = d_stack.top(); d_stack.pop(); if (c == '[') break; } int (*predicate)(int) = s_charClass[d_setIdx].second; for (int idx = 0; idx < 255; ++idx) { if ((*predicate)(idx)) setEscape(idx); } } bobcat-3.19.01/cgi/operatorassign.cc0000644000175000017500000000013712222576524016224 0ustar frankfrank#include "cgi.ih" CGI &CGI::operator=(CGI &&tmp) { fswap(*this, tmp); return *this; } bobcat-3.19.01/cgi/opindex.f0000644000175000017500000000014512223023055014454 0ustar frankfrankinline char const *CGI::operator[](std::string const &key) const { return getenv(key.c_str()); } bobcat-3.19.01/cgi/charrange.cc0000644000175000017500000000067712222576524015127 0ustar frankfrank#include "cgi.ih" void CGIFSA::charRange() { size_t end = static_cast(d_buffer[0]); d_stack.pop(); // hyphen size_t begin = static_cast(d_stack.top()); d_stack.pop(); // first char if (begin <= end) { for(++end; begin != end; ++begin) setEscape(begin); } acceptAll(); // unescape any remaining chars } bobcat-3.19.01/cgi/setmethod.cc0000644000175000017500000000220612222576524015157 0ustar frankfrank#include "cgi.ih" void CGI::setMethod() { char const *cp = (*this)["REQUEST_METHOD"]; if (cp) { string meth(cp); if (meth == "GET") { d_method = GET; return; } if (meth == "POST") { if ((cp = (*this)["CONTENT_LENGTH"])) d_contentLength = A2x(cp); if ((cp = (*this)["CONTENT_TYPE"]) != 0) { string type(cp); string::size_type pos; if ( type.find("multipart/form-data") == 0 && (pos = type.find("boundary=")) != string::npos ) { // don't count trailing \0 d_boundary = type.substr(pos + sizeof("boundary=") - 1); d_boundary.insert(0, "--"); // actual boundary has two // additional - chars } } d_method = POST; return; } } d_status = "GET/POST REQUEST_METHOD not found"; } bobcat-3.19.01/cgi/opinsert2.cc0000644000175000017500000000064512222576524015115 0ustar frankfrank#include "cgi.ih" CGI &CGI::operator<<(std::pair range) { if (!d_activated) { for(auto &target: ranger( d_escape + static_cast(range.first), d_escape + static_cast(range.second) + 1 ) ) target = d_escapeValue; d_escape['\\'] = true; } return *this; } bobcat-3.19.01/changelog0000644000175000017500000017575112260244174013777 0ustar frankfrankbobcat (3.19.01) * Fixed Process's d_closedByChild initialization (used by FreeBSD systems). -- Frank B. Brokken Mon, 30 Dec 2013 11:17:50 +0100 bobcat (3.19.00) * Added Signal::remove, removing a previously added signal handling object. * Redesigned Process so that it (partially) uses the pimpl idiom. Also added the eoi manipulator and several new member functions. * Updated man-pages for Pipe, Redirector, Process, and Signal, -- Frank B. Brokken Sat, 28 Dec 2013 11:16:20 +0100 bobcat (3.18.01) * Fixed a mismatch between SharedMemory::read's declared and defined return type. * Fixed erroneous #include directives in several Shared* class headers -- Frank B. Brokken Fri, 22 Nov 2013 09:15:24 +0100 bobcat (3.18.00) * Added several new classes handling shared memory: ISharedStream, OSharedStream, SharedBlock, SharedMemory, SharedMutex, SharedPos, SharedSegment, SharedStream, and SharedStreambuf * Moved, where possible, nested struct/class definitions not required in the public interface to the internal headers. * The nested class MailHeaders::const_hdr_iterator is used in the public interface: it is now declared in the public interface as well. -- Frank B. Brokken Mon, 18 Nov 2013 12:26:47 +0100 bobcat (3.17.00) * New split members added to the String class, removing the private split facility from Process, which are now superfluous, as they are covered by String's split facilities. * The class BigInt has received several new members and defines a type: - BigInt::Word, is equal to the OpenSSL BN_ULONG type, defining the unsigned long type that is used for storing BIGNUM values; - sizeOfWord() returning the size in bytes of a BigInt::Word; - nWords() returning the number of Words used by the current BigInt value; new at() member; - Word at(size_t index) returns the Word at 'index'. * The source header file of classes defining function templates and inline-members now have their template definitions in .f files, one .f file per function. This change was implemented to simplify function template and inline function maintenance, and to have source clas header files representing class interfaces as cleanly as possible. * Removed the man-page of the deprecated class Errno * All class-specific icmconf files were standardized (and cleaned) * NOTE: the way the linker handles required libraries has changed See, e.g., http://fedoraproject.org/wiki/UnderstandingDSOLinkChange Due to this change programs depending on the bobcat may now require explicit specifications of libraries. Most likely the linke will come with a suggestion. The library libcrypto is a likely candidate for explicit inclusion. If so, use -lcrypto when linking such depending programs. -- Frank B. Brokken Wed, 09 Oct 2013 17:50:04 +0200 bobcat (3.16.00) * Re-implemented process/analyzecommand.cc, improving the wait it handles escaped characters and quoted and double quoted strings. * Added additional demos to the process man-page. * Added the static member Exception::protection to the Exception class. * Gzipped files in the provided documentation no longer contain internal time-stamps. -- Frank B. Brokken Fri, 13 Sep 2013 15:53:51 +0200 bobcat (3.15.00) * Added class IFilterStreambuf, implementing filtering like, e.g., openSSL BIOs. * Added class ISymCryptStreambuf and its base class SymCryptStreambufBase, implementing SSL-provided symmetric encryption and decryption using the IFilterStreambuf design pattern. * Added class IBase64Streambuf and its base class Base64StreambufBase, implementing base64 encoding and decoding, using the IFilterStreambuf design pattern. * Added class IBase64Stream, using a IBase64Streambuf for its std::streambuf. * Added class ISymCryptStream, using a ISymCryptStreambuf for its std::streambuf. * Added class DiffieHellman, implementing Diffie-Hellman shared key computations. * Added the internal use only class FBB, to contain structs, enums, etc. that are used by other Bobcat classes. * Added new constructors to BigInt initializing BigInt values from a series of characters or from a std::string. -- Frank B. Brokken Mon, 26 Aug 2013 15:16:13 +0200 bobcat (3.14.00) * Syslogbuf and SyslogStream received an overhaul, adding several new members. -- Frank B. Brokken Fri, 10 May 2013 11:30:50 +0200 bobcat (3.13.00) * Added new member CGI::param1 * Updated CGI documentation -- Frank B. Brokken Thu, 25 Apr 2013 16:42:05 +0200 bobcat (3.12.00) * Added class Exception, obsoleting class Errno. * All occurrences of Errno in Bobcat were replaced by Exception * The class tt(BigInt) received several new member diophantus (for long long values and BigInt values). See the bigint(3bobcat) man page for details. * Added new class PrimeFactors, factorizing BigInt values. * Added missing OFdStreambuf::pSync member. -- Frank B. Brokken Sun, 24 Feb 2013 13:09:38 +0100 bobcat (3.11.01) * Repaired incorrect #include "../gs/gs" in glob/glob -- Frank B. Brokken Sat, 27 Oct 2012 16:02:58 +0200 bobcat (3.11.00) * Added OFdStreambuf constructor and open member expecting a std::string const & defining the name of the stream to receive the filtered information. * Glob offers an additional constructor allowing users to specify the type of directory entries they are interested in (e.g., DIRECTORY, REGULAR_FILE, or any bitor-ed combination. The flags defined in Bobcat's Stat class are identical to those that are available in Glob. * Glob now uses the pimpl design with all its public members. * Several man-pages were updated, mostly textual corrections. -- Frank B. Brokken Sat, 27 Oct 2012 12:14:35 +0200 bobcat (3.10.01) * Library constrction scripts cleanup so it supports environment variables: LDFLAGS, CPPFLAGS, CXXFLAGS and CXX -- Frank B. Brokken Sun, 22 Jul 2012 13:58:01 +0200 bobcat (3.10.00) * Added class Signal, allowing context to be used by programs receiving signals. * Added to the class User members (egroupid, euserid) to retrieve the effective group and user-ids and a member (inGroup) to determine whether the user is a member of a specified group. * Added to the class Stat a member (access) returning true if specified read, write and/or execute permissions are granted for a provided FBB::User object. -- Frank B. Brokken Thu, 28 Jun 2012 22:29:46 +0200 bobcat (3.01.00) * Repaired a bug in DateTime: its dstCorrection(bool *ok) member failed to set the ok boolean to true if the localime_r performed correctly. * According to the man-page localtime_r does not assume that tzset(3) has been called, but leaves this to the calling program. Localtime_r's man-page states: For portable code tzset should be called before localtime_r(). DateTime::dstCorrection(bool *) now calls tzset before calling localtime_r. -- Frank B. Brokken Mon, 14 May 2012 11:43:08 +0200 bobcat (3.00.02) * Cosmetic split of configile/beginre.cc into two sources, one holding the deprecated member ConfigFile::begin, the other one holding ConfigFile__::begin. * All classes that may throw Bobcat's Errno exceptions now include bobcat/errno in their class-level header files. -- Frank B. Brokken Thu, 10 May 2012 13:50:36 +0200 bobcat (3.00.01) * Re-added deprecated classes and members that were removed in 3.00.00 * Old references to ...bobcat2 in icmake files replaced by references to ...bobcat3 -- Frank B. Brokken Mon, 07 May 2012 17:08:51 +0200 bobcat (3.00.00) * Functionality deprecated in Bobcat < 3.00.00 has been removed. This includes the classes Msg (Use Mstream or Errno), the FnWrap* and ForEach templates (use lamda functions), and AutoPtr / RefCount (use std::shared_ptr or std::unique_ptr) * Arg/ConfigFile/ArgConfig now use the Bridge Design Pattern. Note that this requires (only once) all programs using Arg, ConfigFile or ArgConfig to be recompiled. * Added member int Arg::beyondDashes() returning the index of the first argument beyond a -- argument (or -1) * The 'repeat' function template was improved, now perfectly forwarding arguments to (member) functions repeatedly called by `repeat'. * Replaced climits constants by limits const-expressions * Added TempStream creating a temporary fstream * NOTE: programs depending on the Bobcat shared library most likely must be recompiled. Minor code modifications may be necessary if a program still used Bobcat's deprecated facilities, which are now removed from Bobcat. -- Frank B. Brokken Sat, 05 May 2012 16:50:58 +0200 bobcat (2.22.00) * Repaired bug in ArgConfig: following load() options in the config. file were (sometimes) not found. * ArgConfig option specifications may now have an optional : appended to them. * ConfigFile (and ArgConfig) may use \# in configuration files to specify a literal #. The \ is removed from the configuration line. * Code-cleanup of ArgConfig, adapted argconfig/driver's build script and provided an example config file. * Added missing parameters to ArgConfig's constructors in its man-page. -- Frank B. Brokken Mon, 16 Apr 2012 11:50:40 +0200 bobcat (2.21.01) * Replaced for_each calls by range-based for-loops -- Frank B. Brokken Sat, 21 Jan 2012 16:52:00 +0100 bobcat (2.21.00) * Added new classes: Ranger and PtrIter, see their man-pages for details * Repaired a flaw in hash/hash, appearing with g++-4.7 -- Frank B. Brokken Sat, 07 Jan 2012 13:27:57 +0100 bobcat (2.20.02) * Using rang-based for loops where appropriate; minor cosmetic code changes -- Frank B. Brokken Wed, 04 Jan 2012 13:20:29 +0100 bobcat (2.20.01) * Repaired bug in ReadLineBuf: object was incompletely initialized resulting in intermittendly occurring segfaults. -- Frank B. Brokken Sun, 04 Dec 2011 21:31:12 +0100 bobcat (2.20.00) * Redefined the implementations of the templates in bobcat/binops. -- Frank B. Brokken Thu, 03 Nov 2011 18:42:27 +0100 bobcat (2.19.01) * Repaired bug in BigInt::isqrt * BigInt's destructor called BN_clear, but should have called BN_free. Now repaired. -- Frank B. Brokken Mon, 10 Oct 2011 10:29:08 +0200 bobcat (2.19.00) * The 'BigInt' man-page was adapted to match the actual member and function prototypes mentioned in * Repaired a bug in size-test in BigInt::fromText * The 'binary_search' template was inadvertently dropped from Bobcat's classes and has been added again. * Environment variable name CPPFLAGS changed to CXXFLAGS * Updated README.class-setup overview of classes -- Frank B. Brokken Thu, 22 Sep 2011 20:57:58 +0200 bobcat (2.18.00) * Added missing Stat::operator=(Stat const &other) member. * FnWrap* calls removed from the bobcat library: they are now superfluous as compilers support lambda functions. The FnWrap* classes remain available. * George Danchev observed that static const numeric datamembers (e.g., size_t) using in-class initialization values cause compilation errors when all optimizations are switched off (-O0). These static const data members were replaced by enum values. * Added IfElse and LpromotesR class templates to bobcat/typetrait * The arithmetic operator function templates defined in bobcat/binops now support promotions for classes defining constructors allowing promotions. -- Frank B. Brokken Fri, 17 Jun 2011 10:32:38 +0200 bobcat (2.17.00) * In accordance with C++0x's prototype of move members Bobcat's move constructors and move assignment operators now all use 'Class &&tmp' parameter definitions (where Class should be replaced by the actual class name). Previously defined members specifying 'Class const &&tmp' were retained for backward compatibility, but also generate a `deprecated' warning when used from, e.g., a dynamic library. If such a warning is generated the program dynamically linking to the bobcat library only needs to be recompiled to get rid of the message. * Added new series of function templates in the bobcat/binops header file, making available all binary arithmetic operators for classes already defining (a subset of) the binary assignment operators. The command `man -e bobcat binops' provides the details. -- Frank B. Brokken Mon, 06 Jun 2011 14:35:52 +0200 bobcat (2.16.00) * Removed obsolete bobcatlcgen * All previously inline implemented virtual members are now defined as non-inline members, which should solve an issue with compilers on armel architecture which don't handle inline virtual members correctly. * The 'build' script now uses the -g option by default (set in INSTALL.im). To modify the g++ compilation options change the #define CPPOPT in INSTALL.im. By default it is set to "-O2 -g". To modify the flags `on the fly' set the environment variable CPPFLAGS to the compiler options to use. The options "-isystem tmp -Wall" are always used and should not be altered. bobcat (2.15.02) * Replaced the auto_ptr in Log by a unique_ptr. Since both have equal sizes and are only used in compiled sources (not in inline functions) no recompilation of programs dynamically linking to bobcat is required wrt this change. * The Pattern static data members in the class Cidr are in some situations not properly initialized with g++-4.6. This, e.g., already happens when an empty main() function is linked against the Bobcat library. Although the Pattern objects are not properly initialized, their destructors are nonetheless called when the program ends, causing a segfault. Static object initialization is a known protential source of problems, see, e.g., to cause problem. See also http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.15 In the case of Cidr the problem was easily solved. Each of the two static Pattern members is only used in a single Cidr-member. Removing the static data members from the interface and defining them as static local objects in the member functions using them solves the problem. -- Frank B. Brokken Wed, 11 May 2011 14:26:49 +0200 bobcat (2.15.01) * Repaired flaw in fnwrap, emerging while compiling bisonc++ -- Frank B. Brokken Thu, 05 May 2011 09:35:15 +0200 bobcat (2.15.00) * New version repairs some flaws that became apparent with g++ 4.6. * Re-implemented FnWrap: its size has been halved, FnWrap::unary and FnWrap::binary act identically and are now in fact superseded by the function FBB::context(). * Added README.fnwrap to the set of README files, explaining the FnWrap's inner workings -- Frank B. Brokken Mon, 02 May 2011 19:53:04 +0200 bobcat (2.14.00) * New class: Cidr verifying whether an IP4 address belongs to an IP4 Classless Inter-Domain Routing (CIDR) address block. * New class: StringLine doing line instead of word extraction with operator>>. * Repaired bug in ConfigLine detected by Kees Visser on amd64 architectures causing string to throw an exeption with empty configuration file lines -- Frank B. Brokken Sat, 05 Feb 2011 12:02:08 +0100 bobcat (2.13.00) * Repaired bug in Arg detected by George Danchev sometimes causing segfaults when an undefined long option is specified. * This line added after tagging, but part of 2.13.00: using std::unordered_map instead of std::map with Arg. * Moved public MailHeaders::const_hdr_iterator members from mailheaders.ih back to mailheaders * Cosmetic corrections to man-pages -- Frank B. Brokken Wed, 02 Feb 2011 18:39:50 +0100 bobcat (2.12.00) * FreeBSD flavors lack the fntl flag F_DUPFD_CLOEXEC, so Process::operator| must use a work-around for that flag. The work-around is compiled into Process objects/code when the BOBCAT_DIY_CLOEXEC_ identifier has been defined. It is defined by default in process/process when the identifiers __FreeBSD_kernel__ or __FreeBSD__ are defined. As F_DUPFD_CLOEXEC has been defined by POSIX since 2008 it is possible that it will soon be defined by FreeBSD systems as well. The work-around adds an additional data member to the Process class. Since the data member is the last data member of Process objects it can easily be removed at a later stage when F_DUPFD_CLOEXEX becomes available for FreeBSD systems. * Lacking descriptions of some FBB::CGI members were added to the cgi(3bobcat) man-page. * The CGI class now uses a std::unordered_map, rather than a std::map * Process now supports IOMode::DIRECT * The file README.process-pipe (and support files process-pipe.odp and process-pipe.pdf) were added tot Bobcat's root direcory, describing the inner workings of Process's operator|. -- Frank B. Brokken Sun, 30 Jan 2011 14:51:48 +0100 bobcat (2.11.00) * Repaired bug in Process due to which single quoted process arguments were not correctly passed on to the child process * When using Process::IGNORE_ALL in combination with other Process:IOMode flags an std::invalid_argument exception is thrown * Removed all Errno insertable/throwable manipulator calls from Bobcat * Removed empty source file bigint/checked5.cc * IOStream(istream &, ostream &)'s constructor now also opens the IOStream object (as it always should have done) * OFdStreambuf and IFdStreambuf have a new member (int fd()) returning the File Descriptor. Their descructors are not defined inline anymore (but their implementations have not changed) and they have a new member (close()) closing the streambuf. Closed OFdStreambuf and IFdStreambuf objects can again be opened using open() * Updated several man-pages bobcat (2.10.03) * Matthias Klose detected several bugs/omissions in Bobcat's shared library construction. Now fixed. -- Frank B. Brokken Wed, 29 Dec 2010 17:14:06 +0100 bobcat (2.10.02) * ConfigFile's size() member was missing. Now repaired. -- Frank B. Brokken Sat, 25 Dec 2010 11:02:02 +0100 bobcat (2.10.01) * TableLines' default and move constructor and move assignment operator were accidentally put in the private section of their class. Now public. * Configfile's overloaded assignment operator used non const & argument. Repaired. * CmdFinderBase's overloaded assignment operator cannot be defaulted as it lives in the class's protected section. Added explicit implementation of the overloaded assignment operator. -- Frank B. Brokken Sun, 19 Dec 2010 21:29:26 +0100 bobcat (2.10.00) * Reorganized the class ConfigFile. It used inheritance the wrong way (it inherited to reuse its base class rather than the base class being reused (cf. Herb Sutter's Exceptional C++)) and it suffered from several other flaws. ConfigFile now also supports a move constructor and move overloaded assignment operator. * Repaired ArgConfig::longConfigOpt(string const &longOpt). It checked for the longOpt\b pattern, but \b matches also the - character as a word delimiter. Therefore, pattern xyz-pqr is matched when looking for pattern xyz. It's now using (\s|$) rather than \b. * Reorganized the class MailHeaders. It used inheritance the wrong way (see ConfigFile above). * In addition to the classes that have already been made move-aware, the following classes are now also move-aware: CmdFinderBase, CmdFinder, CGI. Hash, MailHeaders, Stat, TableSupport, TableLines, User (see also README.immovable). * The hash-containers (defined in bobcat/hash) now also support initialization by initializer lists. * The class Milter now uses an unordered_map instead of a map. * The -O3 compilation optimization flag is changed to -O2. G++ for the armel architecture produces an incomplete symbol table when -O3 is used. -- Frank B. Brokken Fri, 17 Dec 2010 14:18:33 +0100 bobcat (2.09.04) * Repaired ArgConfig::option(string *value, ...) members which didn't check for 0-pointers to the string receiving the option's value. -- Frank B. Brokken Mon, 06 Dec 2010 23:38:44 +0100 bobcat (2.09.03) * Repaired Arg::firstNonEmpty which didn't check for 0-pointers to the string receiving the option's value. * Reorganized man-pages to comply with include requirements of Yodl 3.00.0 -- Frank B. Brokken Sun, 05 Dec 2010 19:20:46 +0100 bobcat (2.09.02) * No 'virtual ~Mbuf() = default': destructor removed from Mbuf. -- Frank B. Brokken Thu, 04 Nov 2010 12:45:40 +0100 bobcat (2.09.01) * Mstream::id() now returns a long, rather than an int. See http://developers.sun.com/solaris/articles/ILP32toLP64Issues.html -- Frank B. Brokken Wed, 03 Nov 2010 11:55:17 +0100 bobcat (2.09.00) * Added new classes ReadLineBuf and ReadLineStream reading the standard input using the Gnu readline library, wrapped inside, respectively, a streambuf and an istream. These classes require linkage to libreadline. The class ReadLineBuf is a singleton class. * Added new class ReadLineHistory allowing easy handling of the history accumulated by the ReadLineBuf class. The class ReadLineHistory is a singleton class. * Virtual members of classes derived from std::streambuf were move to the the private section of the classes, making these classes more compliant with Liskov's Substitution Principle. * The 'sync' members of classes derived from std::streambuf can be called from derived classes using a protected 'pSync' member. The IOStreambuf class offers comparable protected 'pSeekoff' and 'pSeekpos' and 'pXsputn', allowing the seek and put operations to be performed on request by classes derived from IOStreambuf. * NOTE: Errno's virtual member what() will be moved to Errno's private section in a future release. The new public member 'why' should be used instead, or std::exception::what() should be used. * The class Msg is now deprecated. Classes Mstream (Message stream) and Mbuf (Message buf) have replaced Msg, and Msg's open members have moved to Errno. Msg will remain in Bobcat for a while, but will eventualy be removed. An error message is displayed (once) if Msg::msg() and Msg::open() are used. -- Frank B. Brokken Thu, 28 Oct 2010 20:17:50 +0200 bobcat (2.08.01) * Checked in overlooked repairs of hostent/destroy.cc and TableSupport::setCols. -- Frank B. Brokken Wed, 05 May 2010 11:13:47 +0200 bobcat (2.08.00) * >>>NOTE<<<: Due to a changed organization of the Table classes all software using the 2.07.04 shared library's Table and TableSupport classes needs to be recompiled. * Added new class TableBuf. A streambuf class allowing table constructions using std::ostream objects * Added new class (only used internally by Bobcat): TableBase, containing the common to TableBuf and Table * Added new class TableLines derived from TableSupport setting separating lines across rows/columns of tables * Reorganized the class TableSupport, moving members erroneously placed in in tablesupport.ih back to the tablesupport header file -- Frank B. Brokken Tue, 04 May 2010 12:14:30 +0200 bobcat (2.07.04) * Virtual destructors cannot have default implementations. Added Fork::~Fork and TableSupport::~TableSupport * Repaired compilation problem in fnwrap/fnwrap appearing with g++-4.5 (using Debian 4.5-20100404-1) * fnwrap/fnwrap needs std::move calls where lvalue references are passed to rvalue references, as templates do not automatically perform the conversion from lvalue refs to rvalue refs. -- Frank B. Brokken Fri, 09 Apr 2010 08:58:49 +0200 bobcat (2.07.03) * Repaired additional bugs in String::unescape; unescape only allows \x, \X is no longer accepted (and was not according to the standard), \0 not followed by octal numbers is now recognized as a 0-byte. * Multi-parameter constructors of Arg::LongOption no longer use default arguments to allow the use of initializer lists, added the explicit constructor Arg::LongOption(char const *name) * Added missing #include to localsocketbase/localsocketbase.ih * Pattern now defines the default end pattern (pattern/pattern0.cc) as "\\b" for the benefit of MAC users who otherwise suffer from the `empty sub-expression' error. This affects ConfigFile and (by implication) programs like XD. It has no known effect on Debian systems. -- Frank B. Brokken Fri, 19 Mar 2010 15:37:02 +0100 bobcat (2.07.02) * Repaired a bug in converting escaped hexadecimal characters in String::unescape, reported by Richard Berendsen. * The FnWrap example is now about FnWrap, not anymore about FnWrap2c -- Frank B. Brokken Wed, 24 Feb 2010 08:33:51 +0100 bobcat (2.07.01) * Minimized class FnWrap's member access rights. FnWrap's inner organization improved. Instead of creating nested FnWrap1 and FnWrap2 objects inheritance is used. Also, all function template implementations were moved to below the class interface. -- Frank B. Brokken Mon, 15 Feb 2010 12:42:49 +0100 bobcat (2.07.00) * TypeTrait now supports tests for rvalue reference types. * FBB::insertable and FBB::throwable are no longer required when using Errno * The gptr() < egptr() checks in underflow() functions (IFdStreambuf and Randbuffer) are superfluous and have been removed. * DateTime's man-page contains a caveat for setMonth. * Fswap's man-page BUGS section is augmented with a warning against swapping streams. * Bobcat's main man-page received an entry referring to the TypeTrait class template. * Repaired cgi/push.cc and cgi/accept.cc * New class: FBB::FnWrap, easier to use than and providing all the features of FnWrap[12]c?. See its man-page for details. * Not-implemented constructors and functions, previously flagged with the // NI comment, are now using '= delete'. Likewise, implementaitions of explicitly implemented empty default constructors were removed and replaced by '= default'. Some con- and destructors were kept due to non-public access. The added destructors were defined in source files, and not in-line to localize the class's Vtables with the destructor's source files. * Compilation of, e.g., Glob::operatorassign.cc produces a warning in g++-4.4. This warning disappears with g++-4.5 and is therefore ignored. * Sources also compile fine with g++-4.5 -- Frank B. Brokken Sat, 13 Feb 2010 15:30:43 +0100 bobcat (2.06.00) * Added BigInt::isqrt (integral sqrt computation) * Added BigInt::swap (swapping the current BigInt object's value with another BigInt object's value * BigInt's members not modifying the current object are now const-correct. * In addition to members modifying a BigInt object new members were added not modifying the current object but returning a temporary BigInt const object holding the result of the computation. All members returning a BigInt const object have an additional c added to their names (e.g. `div' modifies the current object, `divc' does not). As a result of this name standardization the names of several members were modified: `gcd' now modifies the current object, `gcdc' returns a BigInt const. `inverseMod' now modifies the current object, `inverseModc' returns a BigInt const. * Added template function fswap, performing fast swapping operations. * The class Glob is now move-aware (offers move constructor and move assignment operator. In addition it offers a swap member. * Move members in Pattern expect 'Pattern const &&', Pattern offers swap. * Hostent now is now move-aware and offers a member swap. Included Hostent in the namespace FBB. -- Frank B. Brokken Fri, 27 Nov 2009 08:49:24 +0100 bobcat (2.05.00) * BigInt values inserted into streams do not show leading zeroes anymore, except for octal values. * BigInt values can be assigned a value from a textual representation * BigInt values can be extracted from std::istream objects. * BigInt::inverseMod() and BigInt::gcd() are now member functions rather than free functions. * BigInt::setBigEndian() is now a static member function. In general: all members returning a BigInt computed from a set of arguments and not requiring an existing BigInt object are defined as static members. * Added MD_CTX initialization and cleanup calls to DigestBuf * Added MD_CTX initialization call to HMacBuf -- Frank B. Brokken Wed, 23 Sep 2009 15:32:48 +0200 bobcat (2.04.02) * DateTime: DST updated by setXXX() members as well. * EncryptBuf/DecryptBuf now correctly set keylength * EncryptBuf's manpage shows key/block sizes in bytes and provides an illustration showing how to discard initial bytes (commonly used with RC4) * DecryptBuf's requirement of non-empty IV vector has been dropped * Repaired Debian bug #546374, reported by Stefan Ebner -- Frank B. Brokken Sun, 13 Sep 2009 11:38:18 +0200 bobcat (2.04.01) * Some OpenSSL functions (HMAC, Digest) needed unsigned 'int *'s. They got 'size_t *s' causing problems on 64-bit archs (e.g. amd64). Now fixed. -- Frank B. Brokken Fri, 04 Sep 2009 23:48:22 +0200 bobcat (2.04.00) * BigInt has been enhanced and extended. Many members have received new prototypes. * New Class: OHexStreambuf, streambuf derived class writing characters received by it as hex numbers to a specified std::ostream. * New Class: DigestBuf, streambuf derived class computing various types of message digests of the characters received by it. * New Class: HMacBuf, streambuf derived class computing a HMAC hashvalue of the characters received by it. * New Class: EncryptBuf, streambuf derived class encrypting the characters received by it, writing the encrypted information to a specified std::ostream. * New Class: DecryptBuf, streambuf derived class decrypting the encrypted information received by it, writing the decrypted information to a specified std::ostream. -- Frank B. Brokken Wed, 02 Sep 2009 20:41:06 +0200 bobcat (2.03.00) * Bobcat is compiled by g++ --std=c++0x. * Stat::modeStr() bug repaired due to which it always showed rwxrwxrwx * Removed deprecated getPid() member from Fork * Removed deprecated get...Fd() members from Pipe * Removed deprecated get...Fd() members from Selector * Selector's setAlarm() member performs a validity check on the specified alarm time * Selector's wait() member handles no-alarm specifications correctly (i.e., according to the description in the select(2) man-page. * Redirector has a new member: through() * IFdStreambuf::xsgetn() was reimplemented to allow unformated reads from std::istream (and IFdStream) objects without referring to underflow. * InetAddress has new members sockaddr_inPtr() returning pointers to its sockaddr_in data member. * Repaired bugs in DateTime constructors accepting strings, redefined many of DateTime's functionality, see its man page. * (Almost) all unary argument constructors now `explicit' * Constructors that can safely throw exceptions, rather than using `verify' do so from now on. The `verify' member remains, albeit empty, available in the class interfaces. Affected classes: Glob, OneKey, User, Pipe, SocketBase, XPointer * Classes for which a move constructor is useful received a move constructor. Currently: AutoPtr, Glob, Pattern, * insert and extraction operators (operator<<, operator>>) are now defined within the namespace FBB and no longer in the std namespace (except for operator<< defined int msg/msg which is in std::) * Added BigInt as the first (optionally added) class depending on OpenSSL. The plan is to add more openssl-based classes in the (near) future. BigInt wraps OpenSSL's unlimited precision number feature implemented by OpenSSL's BN_ functions. -- Frank B. Brokken Wed, 22 Jul 2009 17:37:27 +0200 bobcat (2.02.03) * Missed another EOF in MultiStreambuf. Now repaired. -- Frank B. Brokken Wed, 06 May 2009 10:36:22 +0200 bobcat (2.02.02) * Repaired incomplete initialization bug in SocketBase * Added Fork::prepareDaemon() performing common actions when starting a daemon child process. * Repaired DST and extraction bugs in DateTime * OFoldStreambuf's inheritance tree now places the OFilterStreambuf ahead of the std::ostream class to prevent strange run-time problems on Macs. * New (static) members: OFoldStream(buf)::leftMargin(), OFoldStream(buf)::rightMargin() * OFoldStream::open() members do not close the foldstream (actually, they didn't do that, but the man-page wrongly suggested they did close the stream). * Cosmetic changes to INSTALL, INSTALL.im and icmake/install * Replaces and extends intermediate release 2.02.01 only made available at SourceForge -- Frank B. Brokken Fri, 03 Apr 2009 16:29:47 +0200 bobcat (2.01.1) * The manipulator FBB::FATAL (cf. man -e bobcat log) now throws an Errno exception (Errno(1)) as per the log man-page, and doesn't call exit(1) anymore. bobcat (2.01.0) * Included cstdio in all .ih files of classes using EOF (required for g++ 4.4) * Moved Table::Element's constructor back to the header file (required for Table::push_back()). * Added Log member level() retrieving the currently set loglevel. * Added Log member instance() as a (preferred) alternative for getInstance(). * LogBuffer::overflow() now has protected access rights. * Stat's lastAccess(), lastChange(), and lastModification() members now return DateTime objects representing the times in UTC. * New class: LC, template class to define and/or declare Local Context structs to be used with the FnWrap[12]c classes (cf man -e bobcat lc as well as the FnWrap[12]c man pages) * Added program `bobcatlcgen' generating a file defining the template class LC for a configurable maximum number of fields of the local context structs (cf. man -e bobcatlcgen) * New class: OFilterStreambuf, std::streambuf specialization implementing an ostream filtering design pattern (cf man -e bobcat ofilterstreambuf) * New class: OFoldStreambuf, OFilterStreambuf specialization folding long lines to lines having configurable left and right margins (cf man -e bobcat ofoldstreambuf) * New class: OFoldStream, wrapper class around OFoldStreambuf (cf man -e bobcat ofoldstream) * New class: lm, implementing a manipulator for OFoldStreams setting their left margin (number of indented blanks) (cf. man -e bobcat lm) * New class: mlm, implementing a manipulator for OFoldStreams modifying their left margin (cf. man -e bobcat mlm) bobcat (2.00.1) * George Danchev detected a compilation problem in ArgConfig's option3.cc: On amd64 size_t doesn't match the U postfix for numeric constants (e.g. 0U) It was repaired by defining a static size_t const zero = 0; bobcat (2.00.0) * Upgrading to version 2.00.0 as many classes have over time received API and ABI changes. * Repaired flaws in and extended/rebuilt the class DateTime. Consult its man-page for the current API. * Deprecated members from other classes (see bobcat's 1.21.1 changelog) were removed. * `build install' no longer zip-compresses the html versions of the man pages, as per the Debian debhelper dh_compress man page. * Hm.... ArgConfig was added to the source tree in 1.21.1, but apparently I forgot to add it to the library. Now repaired. bobcat (1.21.1) * Several man-pages were updated/modified (Config, Log, Process, User, X2a) * ConfigFile: added `std::string const &operator[](size_t idx) const' to the interface offering a basic protection against accidentally modifying the configuration file's lines by clients; added member std::string findKeyTail(std::string key, size_t idx = 1) returning the contents beyond key of the idx-th line containing key. * Process: this class received an extensive overhaul resulting in multiple new members. See the Process man-page for details. Several of its former constructors and members are now deprecated and will be removed in a future release. Existing sources defining Process objects and the shared Bobcat library must be recompiled as the data member organization of Process has substantially been changed. Again consult the Process man-page for details. * Msg: added member open(ofstream &out, std::string const &name, size_t protection) opening an ofstream using a specified protection mode. * DateTime: TriVal's UNKNOWN value was changed; rfc2822() now correctly represents the difference between UTC and local time, allowing for DST. * The deprecated Arg::getInstance() member was removed. Arg::instance() should be used instead. * Added the new class ArgConfig combining the facilities of the Arg and Config classes. -- Frank B. Brokken Sun, 26 Oct 2008 15:46:42 +0100 bobcat (1.20.1) * Removed left-over cout stmnts from DateTime members bobcat (1.20.0) * Removed deprecated members from String, removed the std::string base class from String * Moved inline private members to their internal header files where possible. Users of those classes will never need these inline members, so they can be used from the class interface, thus speeding up compilations. * Removed exception thrown from constructors of the following classes: Arg, Glob, OneKey, Pipe, ServerSocket, SocketBase, User, Xpointer Except for the classes Arg and ServerSocket these classes now define a public member 'verify()' which should be called following the construction of objects of these classes before using any other of their members. The verify() member throws the Errno exception if the object could not properly be constructed. As a safeguard verify() is also called from the classes' destructors, but in some programs that might be rather late, causing surprise for the program's users. The man-pages are updated accordingly. EXISTING PROGRAMS using the classes Arg, Glob, OneKey, Pipe, SocketBase, or User should be recompiled, as the data-organization of objects of these classes has changed. Xpointer's data organization was not altered. To find all source (text) files using the above classes the script scripts/check1.20.0 could be used. * Added missing namespace declarations to glob/driver/driver.cc * Repaired reporting the argv-argument before an undefined option instead of the undefined option itself as in, e.g., tmp/bin/xd --verbose -tm ArgData::ArgData(): unknown option: --verbose or: tmp/bin/xd -tm ArgData::ArgData(): unknown option: tmp/bin/xd * Removed 'throw()' lists from various functions and man-pages (except from several Errno members, as their throw() lists are required by Errno's std::exception base class * Removed inline in inline virtual ~Errno() (needed because of a previous bug in g++, which has now been repaired) * Added missing mode() and specialMode() functions to Stat, and added info to the stat manpage indicating what fields of the 'struct stat' are returned by specific accessor members. * Added DayTime::setWeekday() member to DateTime to alter dates based on the day of the week. DateTime's man-page adapted accordingly. bobcat (1.19.0) * Added the template function binary_search that returning iterator to the location of a found element rather than a bool value (as returned by the std::binary_search algorithm) telling its caller whether the searched for element is present or not * The Process class was given additional functionality allowing better control over the way child processes are started and the Process man-page was updated accordingly * The description of the member `header()' in the man-page of the class Milter was improved * CGI's man-page now contains a common organization of a program using a CGI object bobcat (1.18.1) * Repaired a flaw in Pattern due to which a segfault could occur becasue of a failure to initialize the Finite State Automaton processing Perl-like character-set abbreviations. Also the HANDLING OF BACKSLASHES by Pattern objects was modified: to specify a literal backslash is must now be specified twice. NOTE that this change *may* require some maintenance of patterns that were hard-coded in programs already using the Pattern class. See the `pattern' man-page for details. * Removed all left-over redundant include guards * Renamed all identifiers (macro defines, etc.) that started with _ into names not starting with _. This only affects include-guard identifiers and symbols used internally, so programs using Bobcat should not be affected by this modification. * Added the files README.X11 and README.milter * Several members of FBB::State were not documented in the bobcat/stat man-page: missing documentation is now included (TODO). * Added the class CGI processing forms submitted using the Common Gateway Interface * Added for_each() and repeat() function templates (and their man-pages) * Reorganized the main bobcat man-page, adding a categorization of Bobcat's classes bobcat (1.17.2) * Arg's constructors changed in accordance with the new (?) getopt() function: missing option arguments are now properly recognized and no longer confused with `unknown options' * The Table man-page incorrectly listed `Table const &' as its second argument. The modifier `const' is incorrect as the insertion may imply the addition of empty elements to the table in order to make it rectangular. The `const' modifier was removed from the man-page. bobcat (1.17.1) * Removed Wrap* wrappers from Bisonc++. Use FnWrap* instead. * Added member rfc2822() to DateTime returning the time according to RFC 2822 (e.g., as displayed by the `date -R' command. * Partial construction and installation of the Bobcat library is now supported via #defines in INSTALL.im * Minor modifications to satify g++4-3's #include requirements * TEMPORARILY suppressed the `deprecated header warning' resulting from using ext/hash_map in bobcat/hash. The fix is a kludge: the warning is suppressed by defining the backward warning include guard identifier just prior to including ext/hash_map and by undefining it thereafter. bobcat (1.17.0) * Repaired double free bug in Pattern * Changed the implementation and interface of MailHeaders. See 'man -e bobcat mailheaders' for details * Process::init() member removed. setCommand() added, and constructors no longer call the process start() member. They shouldn't as start() forks, and forking an object that isn't constructed yet seems to be inappropriate. The open() call in init() is now placed in start(). Therefore the correct sequence becomes: Process(), start(), ...(insert/extract)..., stop(). Process::operator=() now performs: stop(), setCommand(), start(). Multiple stops() could be given, so ... stop(), operator=(), ... is acceptable. The Process man-page is updated accordingly. * The DateTime class has been enlarged. It now contains members to reassign individual time components as well as members to compare the (in)equality of the times represented by two DateTime objects. Trailing \n is not inserted anymore if a DateTime object is inserted into an ostream. Operators +, -, += and -= for DateTime rvalues removed, since a date is an interval scaled data type. It is, however, possible to add or subtract seconds (or even struct tm structs) and to add/set values to individual DateTime components. * Implemented lastFail() members in A2x and X2a. See the respective man-pages. bobcat (1.16.1) * The `build' script `library' command bow has an additional optional argument `strip' to strip the shared library. By default the library is not stripped. bobcat (1.16.0) * Leftover `String' in string/unescape replaced by `std::string'. * Added missing A2x.to() member template to A2x (cf. C++ Annotations). bobcat (1.15.0) * The Glob constructor no longer requires a static_cast when multiple flags are specified for its second argument. * The TableSupport class's vline(col) member now writes separator[col] to the output stream if it is available. If it is not available, no action is performed. Similarly, vline() now writes the trailing separator as well as a newline character. This is a more natural default behavior of TableSupport. * The Milter class interface was adapted to libmilter-dev 8.14.1-2, affecting milter/milter and milter/initialize.cc. bobcat (1.14.2) * Added (still) missing headers to glob.ih, log.ih and tablesupport.ih required for proper compilation with g++ 4.3 * The ServerSocket is created with the option SO_REUSEADDR, allowing servers to be restarted immediately following a shutdown of the server. -- Frank B. Brokken Fri, 13 Apr 2007 12:05:11 +0200 bobcat (1.14.1) * Member function template implementations consisting of a single line of code were given the `inline' specification. * The classes Table and TableSupport were redesigned. Their public and protected interfaces changed substantially. * Classes TableSpec, EqualWidth and ColumnWidth were developed for use with the Table class only. They are obsolete and were removed from the Bobcat library. * Added a new class Align allowing users to specify alignment of columns or elements of Table objects. * Added a support script contrib/c_conf contributed by Karel Kubat (karel at e dash unity dot org) * Included several missing header files fixing gcc/g++ 4.3 problems -- Frank B. Brokken Wed, 28 Mar 2007 14:22:16 +0200 bobcat (1.13.1) * All function/member/constructor throw() specifications removed, following Sutter & Alexandrescu's suggestions (except where required by external classes, like std::exception. * RefCount's header missed `public:'. Repaired, thus making relase() et al. public members, conform the RefCount manual page. * Added template class `AutoPtr' * Added template classes FnWrap1, FnWrap1c, FnWrap2, FnWrap2c, obsoleting Wrap1, Wrap1c, Wrap2, Wrap2c. Classes previously depending on the Wrap* classes were modified accordingly: they now use FnWrap* bobcat (1.12.1) * inline virtual destructors have an explicit `inline' mentioned in their class interfaces to prevent compilation problems caused by a small g++ (4.1.2) bug. -- Frank B. Brokken Thu, 30 Nov 2006 13:26:52 +0100 bobcat (1.12.0) * All classes have their inline-functions moved out of the interface. They are now implemented inline below the interface itself. X2a now has a copy constructor and an overloaded assignment operator A2x now has a copy constructor (which was announced in the man-page, but was never implemented). Table's functionality has been enlarged. Consult its manpage for details Redirector's `accessVia' member is now deprecated. Instead `swallow' should be used. The String class's object member functions are now deprecated. Instead static member functions have been defined offering the same functionality. -- Frank B. Brokken Wed, 15 Nov 2006 19:25:49 +0100 bobcat (1.11.0) * The classes Wrap1c, Wrap2 and Wrap2c were fully generalized, now accepting any combination of reference, pointer, const reference or const pointer argument types for both the function called from their operator()() function call operator and (with Wrap1c and Wrap2c) the local context struct. Since this results in an extension of the class's API, I upgraded to the next subversion. Since the Wrap* classes are templated classes, the library hasn't changed, and all programes previously compiled against libbobcat1 should continue to run without any required maintenance. The man-pages were updated accordingly. The icmake-script was updated so that it runs on both icmake 6.xx and the upcoming icmake 7.xx release. Started to move inline definitions of members to below the class interface. Done for a2x and datetime. -- Frank B. Brokken Sat, 14 Oct 2006 14:47:37 +0200 bobcat (1.10.2) * Andreas Jochens noted a build-problem for xpointer/get.cc on amd architectures and kindly provided a patch changing the definition size_t keys into unsigned int keys. His patch was applied to this bobcat version. * Added the file README.optimization describing why the compiler option -O3 is used. * INSTALL.im redefines default DOC and DEVDOC locations to, resp. BASE = "/usr"; DOC = BASE + "/share/doc/libbobcat1"; DOCDEV = BASE + "/share/doc/libbobcat1-dev"; * Removed installation of `lintian overrides' from icmake/install -- Frank B. Brokken Thu, 31 Aug 2006 15:18:45 +0200 bobcat (1.10.1) * Some leftover Academic Free License references were replaced by GPL references. The previously used scripts below make/ are obsolete and were removed from this and future distributions. Icmake should be used instead, for which a top-level script (build) and support scripts in the ./icmake/ directory are available. Icmake is available on a great many architectures. See the file INSTALL (and INSTALL.im, replacing the previously used INSTALL.cf) for further details. Various source adaptations were realized (SF: superfluous): All plain `unsigned' variables were changed to `size_t' datetime: changed include time.h into include ctime removed SF include iostream from datetime/operatorminusis2.cc datetime/operatorminusis3.cc datetime/operatorminusis.cc datetime/operatorplusis2.cc datetime/operatorplusis3.cc fork: changed int d_pid into pid_t pid, various files, manpage adapted gethostent: changed `hostent *' into `struct hostent *' in gethostent.cc iostream: removed SF #include iostream from clear1.cc localclientsocket/localclientsocket: datamember SF localclientsocket/localclientsocket.ih: added includes for connect(2) localserversocket/localserversocket.ih: updated required includes mailheaders/read.cc: removed SF include iostream multistreambuf/multistreambuf: removed SF include iostream pattern/convert.cc: removed SF includes iostream and iomanip process/parentredirections.cc,stop.cc: removed SF include iostream selector/selector: including sys/select.h according to POSIX rather than includes using earlier standards. -- Frank B. Brokken Tue, 26 Jul 2006 18:16:42 -0800 bobcat (1.10.0-1) unstable; urgency=low * License changed to the GNU GENERAL PUBLIC LICENSE. See the file `copyright'. Introduced George Danchev as uploader CmdFinder now properly clears beyond() when using mode USE_FIRST From now on this file will contain the `upstream' changes. The Debian related changes are in changelog.Debian.gz -- Frank B. Brokken Tue, 18 Jul 2006 21:38:21 +0200 bobcat (1.9.0) unstable; urgency=low * Following suggestions made by George Danchev, this version was compiled by the unstable's g++ compiler (version >= 4.1), which unveiled several flaws in the library's class header files. These flaws were removed (i.e., repaired). In order to facilitate compiler selection, the compiler to use is defined in the INSTALL.cf file. The debian control-files (i.e., all files under the debian subdirectory) were removed from the source distribution, which is now also named in accordance with the Debian policy. A diff.gz file was added. At the contents level: the class ConfigFile was extended with two overloaded members index(), returning line offset of the original configuration file associated with a particular line that may be retrieved from the ConfigFile object itself. -- Frank B. Brokken Tue, 4 Jul 2006 21:17:56 +0200 bobcat (1.8.0) unstable; urgency=low * make/install script slightly modified: header files are copied before the compilation starts to prevent unavailable header files. Added the following classes: * CmdFinder and CmdFinderBase: CmdFinder is a class handling command-lookup and command-function associations * OneKey: Objects of the class OneKey allow single-keystroke input (not requiring `Enter' to be pressed. * RefCount: Base class allowing its derived classes to share their memory, using reference counting. Modified the layout and contents of the file README.class-setup to improve the current class organization's representation. -- Frank B. Brokken Mon, 26 Jun 2006 08:42:18 +0200 bobcat (1.7.1) unstable; urgency=low * Bobcat now `lintianized'. The libraries are now in the libbobcat1 and libbocat1-dev packages. The package's info has been upgraded. Note that packages depending on bobcat (e.g., stealth and bisonc++) require an upgrade as well. -- Frank B. Brokken Fri, 26 May 2006 15:02:22 +0200 bobcat (1.7.0) unstable; urgency=low * milter and xpointer are included optionally. `make/library all' includes them automatically New class Indent and associated manipulators implementing indentation defined. ofdstreambuf and ifdstreambuf constructors have additional parameters to either close or keep open the file descriptor that is passed to the constructor. The default situation is for ofdstreambuf to close the file descriptor and for ifdstreambuf to keep de file descriptor open. Thus the new implementation is backward compatible with earlier bobcat versions. Msg has a new free function msgstream() returning the not-cleared msg() stream. This allows certain STL algorithms to be used, see `man -e bobcat msg' wrap1c and wrap2c now also accept const contexts; see, e.g., `man -e bobcat wrap1c'. Errors in wrap2c's template definition repaired. ConfigFile now has additional members beginRE() and endRE(), allowing iterators to produce all lines matching a RE. Repaired ConfigFile in accordance with the man-page: initial ws are now removed from the stored lines, find(target): `target' may be found anywhere within a configuration line. -- Frank B. Brokken Tue, 2 May 2006 19:31:02 +0200 bobcat (1.6.0) unstable; urgency=low * minor repair in Pattern- and Selector manpages added MultiStrambuf, IOStreambuf, IOStream: see the manpages for details. redesigned Process: insertions insert to the child process, extractions extract from the child process. STDOUT and STDERR can or cannot be merged. See the man-page for details. redesigned Arg: same functionality as before, but allows for multiple specifications of options, also those having arguments. When multiple options having arguments are specified, each individual argument is retrievable. added string::escape() `get...' accessors removed from all classes, (Arg, Fork and Pipe) Old names are kept for the time being. -- Frank B. Brokken Mon, 26 Dec 2005 19:04:24 +0100 bobcat (1.5.0) unstable; urgency=low * The general bobcat manpage did not have links to wrap1c and wrap2c. Now Repaired. The Log-class interface is modified. See the man -e bobcat log manpage for details. The main difference is that a static initialize() member is now used to define the static Log-object. Also, logs may be written to stdout using a simpler specification than before. The Log class also supports an open() member, allowing you to open a local Log object after its construction. Added the class Milter, offering a C++ interface to the (sendmail) libmilter API. This class uses the `virtual constructor' Design Pattern to prevent the need for saving and accessing private connection based data using the libmilter api smfi_setpriv() and smfi_getpriv(). See `man -e bobcat milter' for details. Added the class Xpointer, setting and retrieving the X-windows pointer coordinates. With the shared object library, functions from both libmilter and libX11 must be available before a program can be fully linked. To prevent unnessary linking to these libraries, required dummy C functions were added to the bobcat library. When using libmilter and/or libX11, that these libraries should be mentioned to the linker before libbobcat. -- Frank B. Brokken Thu, 8 Dec 2005 20:52:44 +0100 bobcat (1.4.0) unstable; urgency=low * 1.4.0 and beyond: compiled with g++-4.0 compiler series. Minor modifications in the log/log and level/level header files: ::operator<<() changed into operator<<() Further support of the 1.2.x series is discontinued -- Frank B. Brokken Fri, 18 Nov 2005 21:44:13 +0100 bobcat (1.2.1) unstable; urgency=low * added missing constructor description in the Pattern manpage removed leftover cerr insertion from localserversocket::listen() defined default localsocketbase constructor. added /bobcat/localsocketbase/open.cc defined default localserversocket constructor. removed /bobcat/localserversocket/localserversocket1.cc added /bobcat/localserversocket/open.cc defined default localclientsocket constructor. defined LocalClientSocket::open() Pattern missed some throwlists in its implementations. Repaired. -- Frank B. Brokken Thu, 17 Nov 2005 14:05:26 +0100 bobcat (1.2.0) unstable; urgency=low * Added the following classes: localsocketbase - base class for unix domain sockets localserversocket - defines server for unix domain sockets localclientsocket - defined client for unix domain sockets randbuffer - std::streambuf producing random numbers irandstream - istream producing random numbers mailheaders - handles SMTP mail message headers Repaired incorrect header inclusion in datetime. -- Frank B. Brokken Fri, 11 Nov 2005 16:47:31 +0100 bobcat (1.1.2) unstable; urgency=low * Repaired -I statement in make/parameters, and changed tmp/inc into tmp/bobcat (repairs resulting from feedback by Vincent Hecht) Changed the ordering of the classes tablesupport and tablespec in CLASSES -- Frank B. Brokken Thu, 8 Sep 2005 19:40:43 +0200 bobcat (1.1.1) unstable; urgency=low * Removed the compilation dependency on `icmake'. See INSTALL for instructions about how to compile and install bobcat yourself, rather than using the binary distribution -- Frank B. Brokken Sat, 3 Sep 2005 16:47:24 +0200 bobcat (1.1.0) unstable; urgency=low * Added the following classes: FBB::ClientSocket: a socket for tcp-communication with a server. FBB::columnWidth: Manipulator class for the class Table. FBB::DateTime: Manipulations with date and time values. FBB::equalWidth: Manipulator class for the class Table. FBB::GetHostent: Obtains hostent struct from hostname or -address. FBB::Glob: Obtain a list of files matching a certain pattern. FBB::Hostent: Wrapper around the hostent struct. FBB::Hostname: Derived from Hostent, allows the initialization from a FBB::IFdStream: stream extracting information from a device whose file FBB::IFdStreambuf: Input stream buffer initialized by a file descrip- FBB::InetAddress: Base class (no public constructor) for objects repre- FBB::level: Manipulator setting the log-level of FBB::Log objects. FBB::Log: std::ostream handling log messages. FBB::LogBuffer: std::streambuf handling log messages. FBB::OFdStream: stream inserting information into a device whose file FBB::OFdStreambuf: Output stream buffer initialized by a file descrip- tor. FBB::Process: Runs child processes, piping output to parents. FBB::ServerSocket: defines a socket to which clients can connect. FBB::SocketBase: Base class for ClientSocket and ServerSocket. FBB::Stat: Determines file characteristics. FBB::Syslogbuf: streambuf to Buffer generating syslog(3) messages. FBB::SyslogStream: stream to Output stream inserting syslog(3) mes- sages. FBB::Table: Display tables row- or column-wise. FBB::TableSpec: Base class for the class Table. FBB::TableSupport: Support class for the class Table. FBB::User: Determines the current user's parameters from /etc/passwd. Added an examples directory under /usr/share/doc/bobcat-dev Added a contrib directory under /usr/share/doc/bobcat-dev, currently containing the `solib' script making shared libraries o The minor release number will be incremented when new information (classes, documentation, etc.) is added, o The subrelease number will be incremented at bugfixes. o I don't know yet when I'll upgrade the major release number -- Frank B. Brokken Wed, 31 Aug 2005 12:57:03 +0200 bobcat (1.0.0-1) unstable; urgency=low * Initial Release. -- Frank B. Brokken Mon, 15 Aug 2005 11:32:09 +0200 bobcat-3.19.01/cidr/0000755000175000017500000000000012242431634013025 5ustar frankfrankbobcat-3.19.01/cidr/setcidr2.cc0000644000175000017500000000061012222576534015057 0ustar frankfrank#include "cidr.ih" void Cidr::setCidr(istream &fin) { d_cidr.clear(); for (auto &cidrPattern: ranger( istream_iterator(fin), istream_iterator()) ) pushCidr(cidrPattern); if (d_cidr.empty()) throw Exception(1) << "Cidr: " << "no CIDR patterns found on " "cidr-specifications stream"; } bobcat-3.19.01/cidr/cidr3.cc0000644000175000017500000000025012222576534014344 0ustar frankfrank#include "cidr.ih" Cidr::Cidr(Cidr &&tmp) : d_cidr(move(tmp.d_cidr)), d_iter(move(tmp.d_iter)), d_matched(move(tmp.d_matched)), d_last(tmp.d_last) {} bobcat-3.19.01/cidr/cidr.cc0000644000175000017500000000024112222576534014261 0ustar frankfrank#include "cidr.ih" string Cidr::cidr() const { ostringstream out; out << binary2dotted(d_iter->first) << '/' << d_iter->second; return out.str(); } bobcat-3.19.01/cidr/match1.cc0000644000175000017500000000054312222576534014522 0ustar frankfrank#include "cidr.ih" bool Cidr::match(istream &in) { auto end = istream_iterator(); return end != find_if( istream_iterator(in), end, [this](string const &line) { return this->matchLine(line); } ); } bobcat-3.19.01/cidr/last.f0000644000175000017500000000011412223023055014124 0ustar frankfrankinline std::string Cidr::last() const { return binary2dotted(d_last); } bobcat-3.19.01/cidr/binary2dotted.cc0000644000175000017500000000042412222576534016115 0ustar frankfrank#include "cidr.ih" string Cidr::binary2dotted(size_t binary) { ostringstream out; out << (binary >> 24 & 0xff) << '.' << (binary >> 16 & 0xff) << '.' << (binary >> 8 & 0xff) << '.' << (binary & 0xff); return out.str(); } bobcat-3.19.01/cidr/cidr1.cc0000644000175000017500000000013612222576534014345 0ustar frankfrank#include "cidr.ih" Cidr::Cidr(std::string const &cidrPattern) { pushCidr(cidrPattern); } bobcat-3.19.01/cidr/address.f0000644000175000017500000000011212223023055014604 0ustar frankfrankinline std::string const &Cidr::address() const { return d_matched; } bobcat-3.19.01/cidr/driver/0000755000175000017500000000000012222576534014327 5ustar frankfrankbobcat-3.19.01/cidr/driver/build0000755000175000017500000000107512222576534015357 0ustar frankfrank#!/bin/bash ln -sf ../cidr . ln -sf ../cidr.ih . case $1 in (b) rm cidr cidr.ih g++ -DBOBCAT --std=c++0x -I../../tmp -o driver driver.cc \ -lbobcat -L../../tmp/lib -s ;; (o) g++ --std=c++0x -o driver *.cc ../tmp/o/*.o -lbobcat -s ;; (c) g++ --std=c++0x -o driver *.cc -lbobcat -s ;; (*) echo $0 b links to bobcat built by 'build libraries all' echo $0 o links to the files in ../tmp/o echo $0 c links to the files in the current dir only rm -f driver ;; esac rm -f cidr cidr.ih bobcat-3.19.01/cidr/driver/cidrspecs0000644000175000017500000000017712222576534016236 0ustar frankfrank 1.2.3.4/8 # a line with comment 129.125.1.1/16 192.168.1.1/16 Private range (remaining info on a line is ignored). bobcat-3.19.01/cidr/driver/driver.cc0000644000175000017500000000436012222576534016134 0ustar frankfrank #include #include #include #ifdef BOBCAT #include #else #include "cidr" #endif using namespace std; using namespace FBB; int main(int argc, char **argv) { enum Spec { NONE, FILE, CIN }; Spec spec = CIN; ifstream in; if (argc > 1) { Errno::open(in, argv[1]); // file containing cidr-specs spec = FILE; } while (true) { string cidrSpec; if (spec == CIN) { cout << "Specify cidr (empty to quit): "; if (!getline(cin, cidrSpec) || cidrSpec.empty()) break; } try { Cidr cidr; switch (spec) { case NONE: return 0; case FILE: cidr.setCidr(in); spec = NONE; break; case CIN: cidr.setCidr(cidrSpec); } while (true) { cout << "Specify address to test (empty to " << (spec == CIN ? "respec. CIDR" : "quit") << "): "; string address; if (!getline(cin, address) || address.empty()) break; if (!cidr.match(address)) { cout << "Address " << address << " not in "; if (spec == CIN) cout << cidrSpec << '\n'; else cout << "specifications in " << argv[1] << '\n'; } else cout << "Address " << address << " in " << cidr.cidr() << "\n" "Lowest address: " << cidr.first() << "\n" "Highest address: " << cidr.last() << "\n" "CIDR mask: " << cidr.mask() << "\n" "Address: " << cidr.address() << '\n'; } } catch (Errno const &err) { cout << "Oops... " << err.why() << "\n" "Try again...\n"; } } } bobcat-3.19.01/cidr/match2.cc0000644000175000017500000000013112222576534014514 0ustar frankfrank#include "cidr.ih" bool Cidr::match(string const &line) { return matchLine(line); } bobcat-3.19.01/cidr/cidr0000644000175000017500000000463112223023055013666 0ustar frankfrank#ifndef _INCLUDED_BOBCAT_CIDR_ #define _INCLUDED_BOBCAT_CIDR_ #include #include #include #include namespace FBB { class Pattern; class Cidr { typedef std::pair MaskPair; // 1st address, mask value typedef std::vector VectorMaskP; VectorMaskP d_cidr; VectorMaskP::const_iterator d_iter; std::string d_matched; // address matched last size_t d_last; // last address in CIDR public: Cidr() = default; Cidr(std::string const &cidrPattern); // 1 one pattern to check Cidr(std::istream &cidrStream); // 2 stream of patterns Cidr(Cidr &&tmp); // 3 Cidr &operator=(Cidr const &rhs) = default; Cidr &operator=(Cidr &&tmp); // all lines of 'in' are inspected for ip addresses matching // any cidr-specification in d_cidr bool match(std::istream &in); // 1 true means: match found bool match(std::string const &line); // 2 match a single line void setCidr(std::string const &cidrPattern); // 1 void setCidr(std::istream &cidrStream); // 2 // following a successful match the following members return // dotted decimal addresses / maskvalues as strings std::string cidr() const; // CIDR containing address() std::string const &address() const; // .f the address matching a CIDR std::string mask() const; // .f the mask used by cidr() std::string first() const; // .f the 1st address in cidr() std::string last() const; // .f the last address in cidr() // convert "a.b.c.d" to // 32-bits value static size_t dotted2binary(std::string const &dotted); // reverse operation static std::string binary2dotted(size_t binary); private: bool matchLine(std::string const &line); MaskPair parse(std::string const &cidrPattern); void pushCidr(std::string const &cidrPattern); bool compare(MaskPair const &mp, std::string const &address); }; #include "address.f" #include "mask.f" #include "first.f" #include "last.f" } // namespace FBB #endif bobcat-3.19.01/cidr/matchline.cc0000644000175000017500000000151512222576534015311 0ustar frankfrank#include "cidr.ih" // Here we get one line, and want to obtain all its elements matching // the pattern. // Return true once a match is found, else false bool Cidr::matchLine(string const &line) //, Cidr &cidr) { static Pattern sl_pattern("\\b\\d+\\.\\d+\\.\\d+\\.\\d+\\b"); string inspect(line); auto end = d_cidr.end(); while (sl_pattern << inspect) // find the first match in 'inspect' { string const &matched = sl_pattern.matched(); d_iter = find_if( d_cidr.begin(), end, [&, this](MaskPair const &mp) { return this->compare(mp, matched); } ); if (d_iter != end) return true; inspect = sl_pattern.beyond(); } return false; } bobcat-3.19.01/cidr/compare.cc0000644000175000017500000000110612222576534014767 0ustar frankfrank#include "cidr.ih" bool Cidr::compare(MaskPair const &mp, string const &address) { size_t binary = dotted2binary(address); // ~0: all 1s, // << moves in 0s over the masked bits // ~() toggles 1s/0s // | sets the masked bits to 1 in last. size_t last = mp.first | ~(~0 << (32 - mp.second)); if (mp.first <= binary && binary <= last) { d_matched = address; d_last = last; return true; } return false; } bobcat-3.19.01/cidr/cidr.ih0000644000175000017500000000044712222576534014304 0ustar frankfrank#include "cidr" #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/cidr/parse.cc0000644000175000017500000000120612222576534014454 0ustar frankfrank#include "cidr.ih" Cidr::MaskPair Cidr::parse(string const &cidr) { static Pattern sl_empty("^\\s*(#.*)?$"); MaskPair ret {0, 0}; if (sl_empty << cidr) // empty line or comment return ret; ret = MaskPair{dotted2binary(cidr), 32}; size_t pos = cidr.find_first_of('/'); if (pos != string::npos) { ret.second = A2x(cidr.substr(pos + 1)); if (A2x::lastFail()) throw Exception(1) << "Cidr: " << "invalid CIDR: `" << cidr << '\''; ret.first = ret.first >> (32 - ret.second) << (32 - ret.second); } return ret; } bobcat-3.19.01/cidr/first.f0000644000175000017500000000012412223023055014311 0ustar frankfrankinline std::string Cidr::first() const { return binary2dotted(d_iter->first); } bobcat-3.19.01/cidr/cidr2.cc0000644000175000017500000000011212222576534014340 0ustar frankfrank#include "cidr.ih" Cidr::Cidr(istream &fin) { setCidr(fin); } bobcat-3.19.01/cidr/dotted2binary.cc0000644000175000017500000000071212222576534016115 0ustar frankfrank#include "cidr.ih" size_t Cidr::dotted2binary(std::string const &dotted) { size_t ret = 0; istringstream in(dotted); for (size_t idx = 0; idx != 4; ++idx) { size_t byte; if (!(in >> byte)) throw Exception(1) << "Cidr: " << "invalid address: `" << dotted << '\''; ret <<= 8; ret += byte; in.ignore(); } return ret; } bobcat-3.19.01/cidr/mask.f0000644000175000017500000000011212223023055014112 0ustar frankfrankinline std::string Cidr::mask() const { return X2a(d_iter->second); } bobcat-3.19.01/cidr/pushcidr.cc0000644000175000017500000000024412222576534015164 0ustar frankfrank#include "cidr.ih" void Cidr::pushCidr(string const &cidrPattern) { MaskPair spec = parse(cidrPattern); if (spec.second) d_cidr.push_back(spec); } bobcat-3.19.01/cidr/operatorassign.cc0000644000175000017500000000017312222576534016404 0ustar frankfrank#include "cidr.ih" #include "../iuo/iuo" Cidr &Cidr::operator=(Cidr &&tmp) { fswap(*this, tmp); return *this; } bobcat-3.19.01/cidr/setcidr1.cc0000644000175000017500000000017312222576534015062 0ustar frankfrank#include "cidr.ih" void Cidr::setCidr(std::string const &cidrPattern) { d_cidr.clear(); pushCidr(cidrPattern); } bobcat-3.19.01/clientsocket/0000755000175000017500000000000012242431634014573 5ustar frankfrankbobcat-3.19.01/clientsocket/connect.cc0000644000175000017500000000033012222576540016533 0ustar frankfrank#include "clientsocket.ih" int ClientSocket::connect() { if (::connect(socket(), sockaddrPtr(), size()) < 0) throw Exception() << "ClientSocket::connect(): " << errnodescr; return socket(); } bobcat-3.19.01/clientsocket/clientsocket1.cc0000644000175000017500000000017212222576540017656 0ustar frankfrank#include "clientsocket.ih" ClientSocket::ClientSocket(string const &host, uint16_t port) : SocketBase(host, port) {} bobcat-3.19.01/clientsocket/driver/0000755000175000017500000000000012222576540016072 5ustar frankfrankbobcat-3.19.01/clientsocket/driver/build0000755000175000017500000003074012222576540017123 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/client // script generated by the C++ icmake script version 1.61 /* Configurable defines for the build script: BISON++: only to be defined if bison++ is to be used in the subdirectory 'parser' on the file 'grammar', generating 'parser.cc' and 'parser.h' in that directory. FLEX++: only to be defined if flex++ is to be used in the subdirectory 'scanner' on the file 'yylex', generating 'yylex.cc' CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ //#define BISON++ //#define FLEX++ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* COMPILER: "g++" for C++ sources. Do not change this, unless you're sure you want something else. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking USE_LIBRARY: define this if you want a library for the object modules. Undefined by default: so NO LIBRARY IS USED. PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed. (default: defined) RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //Do not change the next define unless you know what you're doing: #define COMPILER "g++" // COPT: the set of C-options #define COPT "-Wall" #define ECHO_REQUEST ON // #define GDB // Extra libraries required. Remove lib and .a from the library names. // E.g., #define LIBS "m Xt" to link libm.a and libXt.a explicitly // Specify libs from the most specific to the most general one. #define LIBS "bobcat" // Extra library-paths required. // E.g., #define LIBPATH "/some/path /some/other/path" to search these paths // apart from the default paths #define LIBPATH "" // uncomment if you WANT to use a library // #define USE_LIBRARY #define PROGRAM #define RELINK // DO NOT ALTER THINGS BELOW THIS LINE string // contain options for libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, lopt, libxxxa; // expanded lib-name int relink; // internally used: != 0 to relink string ofiles, // wildcards for o-files sources, // sources to be used wild, // wildcard of extension current; // contains name of current dir. /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list #ifdef USE_LIBRARY objfile = change_ext(file, "o"); // make obj-filename #else objfile = "./o/" + change_ext(file, "o"); // make obj-filename #endif if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* parser.im */ void parser() { chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); } /* scanner.im */ void scanner() { chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", #ifdef INTERACTIVE "-I", #endif "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef USE_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { #ifndef RELINK if ( relink // new library, new main.obj || !exists(exe) // final program doesn't exist ) #endif { printf("\n"); exec(COMPILER, "-o", exe, #ifdef USE_LIBRARY "-l" + library, #else ofiles, #endif libs, "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; #ifndef USE_LIBRARY if (!exists("o")) system("mkdir o"); #endif if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) { #ifdef USE_LIBRARY exec(COMPILER, "-c " COPT + " " + copt + " " + nextfile); #else exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o") + " " COPT + " " + copt + " " + nextfile); #endif } relink = 1; printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { list arlist, objlist; string to, from; objlist = makelist("*.o"); if (!sizeof(objlist)) return; printf("\n"); relink = 1; exec("ar", "rvs", library, "*.o"); exec("rm", "*.o"); printf("\n"); } void prefix_class(string class_id) { list o_files; string o_file; int i; o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(wild, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix, .a suffix if main is given here, libmain.a is created) string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int n, index; list classes; string cwd; #ifdef BISON++ CLASSES += "parser "; if (exists("parser")) // subdir parser exists parser(); #endif #ifdef FLEX++ CLASSES += "scanner "; if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes cwd = chdir("."); ofiles = "o/*.o"; // std set of o-files classes = strtok(CLASSES, " "); // list of classes if (n = sizeof(classes)) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use wild = sources; // make library name libxxxa = chdir(".") + "lib" + library + ".a"; // first process all classes for (index = 0; index < n; index++) { current = element(index, classes); // next class to process chdir(current); // change to directory current = "subdir " + current; std_cpp (libxxxa); // compile all files chdir( cwd); // go back to parent dir } current = "auxiliary " + wild + " files"; std_cpp (libxxxa); // compile all files in current dir for (index = 0; index < n; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. #ifdef USE_LIBRARY prefix_class((string)index); // prefix class-number for .o files updatelib(libxxxa); #endif chdir(cwd); // go back to parent dir } current = ""; // no class anymore #ifdef USE_LIBRARY updatelib(libxxxa); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); } void main() { echo(ECHO_REQUEST); sources = "*.cc"; setlibs(); #ifdef GDB copt = "-g"; #endif #ifdef PROGRAM cpp_make ( "client.cc", // program source "client", // program library "client" // binary program ); #else cpp_make ( "", "client", // program library "" ); #endif } bobcat-3.19.01/clientsocket/driver/client.cc0000644000175000017500000000301612222576540017657 0ustar frankfrank#include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) { cerr << "Provide servername and port number\n"; return 1; } size_t port = A2x(argv[2]); ClientSocket client(argv[1], port); int fd = client.connect(); string line; cout << "Connecting to socket " << fd << endl << "address = " << client.dottedDecimalAddress() << ", " << endl << "communication through port " << client.port() << endl; IFdStream in(fd); // stream to read from OFdStream out(fd); // stream to write to while (true) { // Ask for a textline, stop if empty / none cout << "? "; if (!getline(cin, line) || line.length() == 0) return 0; cout << "Line read: " << line << endl; // Return the line to the server out << line.c_str() << endl; cout << "wrote line\n"; // Wait for a reply from the server getline(in, line); cout << "Answer: " << line << endl; } return 0; } catch (Errno const &err) { cerr << err.why() << "\n" << "Can't connect to " << argv[1] << ", port " << argv[2] << endl; return 1; } bobcat-3.19.01/clientsocket/clientsocket.ih0000644000175000017500000000024012222576540017604 0ustar frankfrank#include "clientsocket" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/clientsocket/clientsocket0000644000175000017500000000064212222576540017213 0ustar frankfrank#ifndef INCLUDED_BOBCAT_CLIENTSOCKET_ #define INCLUDED_BOBCAT_CLIENTSOCKET_ #include #include namespace FBB { class ClientSocket: public SocketBase { public: // host may be address or name ClientSocket(std::string const &host, uint16_t port); int connect(); // returns fd (socket) to talk to the server }; } // FBB #endif bobcat-3.19.01/cmdfinder/0000755000175000017500000000000012226264364014045 5ustar frankfrankbobcat-3.19.01/cmdfinder/opis1.f0000644000175000017500000000021112223023055015224 0ustar frankfranktemplate inline CmdFinder &CmdFinder::operator=(CmdFinder &&tmp) { FBB::fswap(*this, tmp); return *this; } bobcat-3.19.01/cmdfinder/cmdfinder1.f0000644000175000017500000000026412223023055016215 0ustar frankfranktemplate CmdFinder::CmdFinder(Entry const *begin, Entry const *end, size_t mode) : CmdFinderBase(mode), d_count(0), d_begin(begin), d_end(end) {} bobcat-3.19.01/cmdfinder/cmdfinder0000644000175000017500000000326712223023055015716 0ustar frankfrank#ifndef INCLUDED_BOBCAT_CMDFINDER_ #define INCLUDED_BOBCAT_CMDFINDER_ #include #include #include #include namespace FBB { template class CmdFinder: public CmdFinderBase { friend class MatchKey; size_t d_count; protected: typedef FP FunctionPtr; // define template type // as a named type // elements of the array // of keys/f-ptrs typedef std::pair Entry; private: Entry const *d_begin; Entry const *d_end; protected: CmdFinder(Entry const *begin, Entry const *end, // 1 size_t mode = 0); CmdFinder(CmdFinder &&tmp); // 2 CmdFinder &operator=(CmdFinder const &rhs) = default; CmdFinder &operator=(CmdFinder &&tmp); // opis1 FP findCmd(std::string const &cmd); size_t count() const; private: class MatchKey { FP *d_fp; CmdFinder *d_cmdFinder; public: MatchKey(FunctionPtr *fp, CmdFinder *cmdFinder); // 1 bool operator()(CmdFinder::Entry const &entry); // opfun }; bool match(std::string const &key) const; }; #include "cmdfinder1.f" #include "cmdfinder2.f" #include "count.f" #include "findcmd.f" #include "opis1.f" #include "match.f" #include "matchkey1.f" #include "opfun.f" } // FBB #endif bobcat-3.19.01/cmdfinder/opfun.f0000644000175000017500000000031712223023055015327 0ustar frankfranktemplate bool CmdFinder::MatchKey::operator()(CmdFinder::Entry const &entry) { if (!d_cmdFinder->match(entry.first)) return false; *d_fp = entry.second; return true; } bobcat-3.19.01/cmdfinder/driver/0000755000175000017500000000000012222576532015337 5ustar frankfrankbobcat-3.19.01/cmdfinder/driver/build0000755000175000017500000000007412222576531016364 0ustar frankfrank#!/bin/sh g++ driver.cc ../../cmdfinderbase/*.cc -lbobcat bobcat-3.19.01/cmdfinder/driver/driver.cc0000644000175000017500000000574412222576532017153 0ustar frankfrank#include #include //#include #include "../cmdfinder" using namespace std; using namespace FBB; // Define a class `Command' in which the array s_action defines the // command-function associations. Command is derived from CmdFinder, // specifying the prototype of the member functions to be called class Command: public CmdFinder { static Entry s_action[]; bool add() const // some member functions { cout << "add called: command was `" << cmd() << "'\n"; if (beyond().length()) cout << "Beyond " << cmd() << " `" << beyond() << "'\n"; return true; } bool error() const { cout << "unrecognized command: `" << cmd() << "' called\n" << count() << " matching alternatives found\n"; return true; } bool quit() const { cout << "quit called: quitting this series\n"; return false; } public: Command(); // Declare the default constructor bool run(std::string const &cmd) // run a command { return (this->*findCmd(cmd))(); // execute the command matching // 'cmd' } }; // Define command-function associations. Note that the last is given an empty // command-text. This is not required, a command text could have been // specified for the last command as well. Command::Entry Command::s_action[] = { Entry("add", &Command::add), Entry("quit", &Command::quit), Entry("", &Command::error), }; // Define the default constructor Command::Command() // Define the default constructor : // Note the use of `FunctionPtr' CmdFinder(s_action, s_action + sizeof(s_action) / sizeof(Entry)) {} void run(Command &cmd, char const *descr, size_t mode = 0) { if (mode) cmd.setMode(mode); cout << "Enter 5 x a command using " << descr << ".\n"; for (size_t idx = 0; idx++ < 5; ) { cout << "Enter command " << idx << ": "; string text; getline(cin, text); if (!cmd.run(text)) // run a command break; } } int main() { Command cmd; // define a command // enter 5 commands using the default mode run (cmd, "the default mode"); run (cmd, "abbreviated commands", Command::UNIQUE); run (cmd, "abbreviated case-insensitive commands", Command::UNIQUE | Command::INSENSITIVE); run (cmd, "abbreviated command lines", Command::USE_FIRST | Command::UNIQUE); run (cmd, "abbreviated case-insensitive command lines", Command::USE_FIRST | Command::UNIQUE | Command::INSENSITIVE); return 0; } bobcat-3.19.01/cmdfinder/count.f0000644000175000017500000000013212223023055015323 0ustar frankfranktemplate inline size_t CmdFinder::count() const { return d_count; } bobcat-3.19.01/cmdfinder/cmdfinder2.f0000644000175000017500000000025512223023055016216 0ustar frankfranktemplate CmdFinder::CmdFinder(CmdFinder &&tmp) : CmdFinderBase(move(tmp)), d_count(tmp.d_count), d_begin(tmp.d_begin), d_end(tmp.d_end) {} bobcat-3.19.01/cmdfinder/matchkey1.f0000644000175000017500000000022212223023055016061 0ustar frankfranktemplate CmdFinder::MatchKey::MatchKey(FunctionPtr *fp, CmdFinder *cmdFinder) : d_fp(fp), d_cmdFinder(cmdFinder) {} bobcat-3.19.01/cmdfinder/match.f0000644000175000017500000000017412223023055015275 0ustar frankfranktemplate inline bool CmdFinder::match(std::string const &key) const { return (this->*d_match)(key); } bobcat-3.19.01/cmdfinder/findcmd.f0000644000175000017500000000115012223023055015600 0ustar frankfranktemplate FP CmdFinder::findCmd(std::string const &cmd) { (this->*d_useCmd)(cmd); // store the cmd to use FunctionPtr fp; MatchKey matchKey(&fp, this); // create an object matching // a cmd with a key // count the number of occurrences d_count = std::count_if(d_begin, d_end, matchKey); return d_count == 1 ? fp // return fp if cmd found : // otherwise return the last fptr (d_end - 1)->second; } bobcat-3.19.01/cmdfinderbase/0000755000175000017500000000000012242431634014672 5ustar frankfrankbobcat-3.19.01/cmdfinderbase/cmd.f0000644000175000017500000000011312223023055015570 0ustar frankfrankinline std::string const &CmdFinderBase::cmd() const { return d_cmd; } bobcat-3.19.01/cmdfinderbase/oparrow.f0000644000175000017500000000016112223023055016521 0ustar frankfrankinline std::string const *RE_iterator::operator->() const { return &*d_vsIter[d_idx]; } bobcat-3.19.01/cmdfinderbase/size.f0000644000175000017500000000010712223023055016002 0ustar frankfrankinline size_t ConfigFile__::size() const { return d_line.size(); } bobcat-3.19.01/cmdfinderbase/opneg.f0000644000175000017500000000015312223023055016141 0ustar frankfrankinline int operator-(RE_iterator const &lhs, RE_iterator const &rhs) { return lhs.d_idx - rhs.d_idx; } bobcat-3.19.01/cmdfinderbase/findkey.f0000644000175000017500000000022212223023055016457 0ustar frankfrankinline string ConfigFile__::findKey(string const &keyPattern, size_t count) { return searchFor("^\\s*" + keyPattern + "\\s+(\\S+)", count); } bobcat-3.19.01/cmdfinderbase/beyond.f0000644000175000017500000000012412223023055016307 0ustar frankfrankinline std::string const &CmdFinderBase::beyond() const { return d_beyond; } bobcat-3.19.01/cmdfinderbase/matchexact.f0000644000175000017500000000015612223023055017155 0ustar frankfrankinline bool CmdFinderBase::matchExact(string const &key) const { return d_cmd == key && d_cmd.length(); } bobcat-3.19.01/cmdfinderbase/matchuniqueinsensitive.cc0000644000175000017500000000033112222576537022014 0ustar frankfrank#include "cmdfinderbase.ih" bool CmdFinderBase::matchUniqueInsensitive(std::string const &key) const { return d_cmd.length() && String::lc(key).find(String::lc(d_cmd)) != string::npos; } bobcat-3.19.01/cmdfinderbase/cmdfinderbase.ih0000644000175000017500000000030212223023055017766 0ustar frankfrank#include "cmdfinderbase" #include #include using namespace std; using namespace FBB; #include "matchexact.f" #include "matchunique.f" #include "matchinsensitive.f" bobcat-3.19.01/cmdfinderbase/casefinder.f0000644000175000017500000000027212223023055017136 0ustar frankfrankinline bool ConfigFile__::casefinder(string const &haystack, string const &needle) { return strcasestr(haystack.c_str(), needle.c_str()) != 0; } bobcat-3.19.01/cmdfinderbase/index1.f0000644000175000017500000000012112223023055016214 0ustar frankfrankinline size_t ConfigFile__::index(size_t lineNr) { return d_index[lineNr]; } bobcat-3.19.01/cmdfinderbase/cmdfinderbase1.cc0000644000175000017500000000024012222576537020056 0ustar frankfrank//#include "cmdfinderbase.ih" // //CmdFinderBase::CmdFinderBase(CmdFinderBase &&tmp) //: // d_cmd(move(tmp.d_cmd)), // d_beyond(move(tmp.d_beyond)) //{} bobcat-3.19.01/cmdfinderbase/opstar.f0000644000175000017500000000013212223023055016336 0ustar frankfrankinline std::string const &RE_iterator::operator*() const { return *d_vsIter[d_idx]; } bobcat-3.19.01/cmdfinderbase/findkeytail.f0000644000175000017500000000023112223023055017331 0ustar frankfrankinline string ConfigFile__::findKeyTail(string const &keyPattern, size_t count) { return searchFor("^\\s*" + keyPattern + "\\s+(.*)\\s*$", count); } bobcat-3.19.01/cmdfinderbase/begin.f0000644000175000017500000000013712223023055016117 0ustar frankfrankinline ConfigFile__::const_iterator ConfigFile__::begin() const { return d_line.begin(); } bobcat-3.19.01/cmdfinderbase/setcommenthandling.f0000644000175000017500000000015012223023055020711 0ustar frankfrankinline void ConfigFile__::setCommentHandling(Comment type) { d_rmComment = type == RemoveComment; } bobcat-3.19.01/cmdfinderbase/finder.f0000644000175000017500000000020512223023055016276 0ustar frankfrankinline bool ConfigFile__::finder(string const &haystack, string const &needle) { return haystack.find(needle) != string::npos; } bobcat-3.19.01/cmdfinderbase/cmdfinderbase1.f0000644000175000017500000000011012223023055017671 0ustar frankfrankinline CmdFinderBase::CmdFinderBase(size_t mode) { setMode(mode); } bobcat-3.19.01/cmdfinderbase/opneq.f0000644000175000017500000000015012223023055016150 0ustar frankfrankinline bool operator!=(RE_iterator const &lhs, RE_iterator const &rhs) { return not (lhs == rhs); } bobcat-3.19.01/cmdfinderbase/end.f0000644000175000017500000000013312223023055015575 0ustar frankfrankinline ConfigFile__::const_iterator ConfigFile__::end() const { return d_line.end(); } bobcat-3.19.01/cmdfinderbase/usecmd.cc0000644000175000017500000000017312222576537016474 0ustar frankfrank#include "cmdfinderbase.ih" void CmdFinderBase::useCmd(std::string const &cmd) { d_beyond.erase(); d_cmd = cmd; } bobcat-3.19.01/cmdfinderbase/matchinsensitive.f0000644000175000017500000000024212223023055020405 0ustar frankfrankinline bool CmdFinderBase::matchInsensitive(string const &key) const { return String::casecmp(d_cmd, key) == 0 && d_cmd.length(); } bobcat-3.19.01/cmdfinderbase/usefirstcmd.cc0000644000175000017500000000044212222576537017543 0ustar frankfrank#include "cmdfinderbase.ih" void CmdFinderBase::useFirstCmd(std::string const &cmd) { istringstream in(cmd); d_beyond.erase(); // clear any old remaining `beyond' info in >> d_cmd >> d_beyond; string trailer; getline(in, trailer); d_beyond += trailer; } bobcat-3.19.01/cmdfinderbase/setmode.cc0000644000175000017500000000145512222576537016660 0ustar frankfrank#include "cmdfinderbase.ih" void CmdFinderBase::setMode(size_t mode) { if (mode & ~s_all) throw Exception(1) << "CmdFinder: " << "mode 0x" << hex << mode << " not recognized (allowed bits: 0x" << s_all << ")"; d_useCmd = mode & USE_FIRST ? &CmdFinderBase::useFirstCmd : &CmdFinderBase::useCmd; switch (mode & (UNIQUE | INSENSITIVE)) { case 0: d_match = &CmdFinderBase::matchExact; break; case UNIQUE: d_match = &CmdFinderBase::matchUnique; break; case INSENSITIVE: d_match = &CmdFinderBase::matchInsensitive; break; default: d_match = &CmdFinderBase::matchUniqueInsensitive; break; } } bobcat-3.19.01/cmdfinderbase/cmdfinderbase0000644000175000017500000000412012223023055017371 0ustar frankfrank#ifndef INCLUDED_BOBCAT_CMDFINDERBASE_ #define INCLUDED_BOBCAT_CMDFINDERBASE_ #include #include namespace FBB { // Key: the textual elements in the char */function * arrays (e.g., help) // Cmd: what is entered interactively (e.g., h, hel, or help) class CmdFinderBase { enum: size_t // mask testing the Mode-validity { s_all = (1 << 3) - 1 }; std::string d_cmd; std::string d_beyond; public: // The default is: // Use the key as provided // Match case sensitively and exactly // The last function is the catch-all enum Mode { USE_FIRST = 1 << 0, // Use/rm the first word from the key UNIQUE = 1 << 1, // Unique cmd abbreviations are OK INSENSITIVE = 1 << 2, // Key-cmd matched case insensitively }; void setMode(size_t mode); // to change the mode afterwards protected: explicit CmdFinderBase(size_t mode = 0); // 1.f std::string const &beyond() const; // .f info beyond the command std::string const &cmd() const; // .f the used command // returns true if the cmd represents the // key bool (CmdFinderBase::*d_match)(std::string const &key) const; // stores the command to use void (CmdFinderBase::*d_useCmd)(std::string const &cmd); private: void useCmd(std::string const &key); void useFirstCmd(std::string const &key); bool matchExact(std::string const &key) const; // .f // the command is found in the key bool matchUnique(std::string const &key) const; // .f bool matchInsensitive(std::string const &key) const; bool matchUniqueInsensitive(std::string const &key) const; }; #include "cmdfinderbase1.f" #include "beyond.f" #include "cmd.f" } // FBB #endif bobcat-3.19.01/cmdfinderbase/matchunique.f0000644000175000017500000000020212223023055017347 0ustar frankfrankinline bool CmdFinderBase::matchUnique(string const &key) const { return key.find(d_cmd) != string::npos && d_cmd.length(); } bobcat-3.19.01/cmdfinderbase/setsearchcasing.f0000644000175000017500000000016412223023055020201 0ustar frankfrankinline void ConfigFile__::setSearchCasing(SearchCasing type) { d_caseSensitive = type == SearchCaseSensitive; } bobcat-3.19.01/cmdfinderbase/opindex.f0000644000175000017500000000014112223023055016474 0ustar frankfrankinline std::string const &ConfigFile__::operator[](size_t idx) const { return d_line[idx]; } bobcat-3.19.01/cmdfinderbase/endre.f0000644000175000017500000000017212223023055016127 0ustar frankfrankinline ConfigFile__::const_RE_iterator ConfigFile__::endRE() const { return RE_iterator(d_vsIter, d_vsIter.size()); } bobcat-3.19.01/cmdfinderbase/index2.f0000644000175000017500000000015612223023055016225 0ustar frankfrankinline size_t ConfigFile__::index(const_iterator const &iterator) { return d_index[iterator - begin()]; } bobcat-3.19.01/configfile/0000755000175000017500000000000012242431634014211 5ustar frankfrankbobcat-3.19.01/configfile/begin.cc0000644000175000017500000000016212222576537015615 0ustar frankfrank#include "configfile.ih" ConfigFile::const_iterator ConfigFile::begin() const { return d_ptr->begin(); } bobcat-3.19.01/configfile/configfile.ih0000644000175000017500000000757212223023055016644 0ustar frankfrank#include "configfile" #include #include #include #include #include #include using namespace std; using namespace FBB; // Lines are stored with initial WS removed. // If a line ends in \, then the next line (initial WS removed) // is appended to the current line. // Information at and beyond the first # on individual lines is removed // if the rmComment flag is set to true (\# is converted to a #-character) // Then, lines containing only blanks and tabs are not stored namespace FBB { class ConfigFile__: public CFEnums__ { std::vector d_line; bool d_rmComment; bool d_caseSensitive; bool d_indices; size_t d_rawIndex; size_t d_nextIndex; std::vector d_index; // contains iterators to lines matching REs typedef std::vector::const_iterator VsIterator; typedef std::vector VsIterVector; VsIterVector d_vsIter; std::string d_re; mutable Pattern d_pattern; public: explicit ConfigFile__(Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); // Name of the config file explicit ConfigFile__(std::string const &fname, Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); ConfigFile__(ConfigFile__ const &rhs) = default; ConfigFile__(ConfigFile__ &&tmp) = default; ConfigFile__ &operator=(ConfigFile__ &&tmp) = default; ConfigFile__ &operator=(ConfigFile__ const &rhs) = default; void setCommentHandling(Comment type); // .i void setSearchCasing(SearchCasing type); // .i void open(std::string const &fname); const_iterator begin() const; // .i const_iterator end() const; // .i const_RE_iterator beginRE(std::string const &re); const_RE_iterator endRE() const; // .i std::pair beginEndRE(std::string const &re); const_iterator find(std::string const &target) const; const_iterator findRE(std::string const &re) const; std::string findKey(std::string const &key, size_t count); // .i std::string findKeyTail(std::string const &key, size_t count); // .i size_t index(size_t lineNr); // 1.i size_t index(const_iterator const &iterator); // 2.i std::string const &operator[](size_t idx) const; // opindex.i size_t size() const; // .i private: static void trimLeft(std::string &line); static void trimRight(std::string &line, bool appendNext); bool rmCommentAndEscapes(std::string &line); bool nextLine(std::istream &inStream, std::string &dest); void resetVsIter(std::string const &re); std::string searchFor(std::string const &keyPattern, size_t count); static bool finder(std::string const &haystack, // .i std::string const &needle); static bool casefinder(std::string const &haystack, // .i std::string const &needle); }; } // FBB #include "begin.f" #include "casefinder.f" #include "end.f" #include "endre.f" #include "finder.f" #include "findkey.f" #include "findkeytail.f" #include "index1.f" #include "index2.f" #include "opindex.f" #include "setcommenthandling.f" #include "setsearchcasing.f" #include "size.f" bobcat-3.19.01/configfile/beginendre.cc0000644000175000017500000000031612222576537016634 0ustar frankfrank#include "configfile.ih" ConfigFile::RE_iteratorPair ConfigFile::beginEndRE(std::string const &re) { auto begin = d_ptr->beginRE(re); RE_iteratorPair ret(begin, d_ptr->endRE()); return ret; } bobcat-3.19.01/configfile/oparrow.f0000644000175000017500000000016112223023055016040 0ustar frankfrankinline std::string const *RE_iterator::operator->() const { return &*d_vsIter[d_idx]; } bobcat-3.19.01/configfile/find.cc0000644000175000017500000000075012222576537015454 0ustar frankfrank#include "configfile.ih" vector::const_iterator ConfigFile__::find(string const &target) const { return find_if( begin(), end(), [&](string const &haystack) { return (d_caseSensitive ? finder : casefinder) (haystack, target); } ); } vector::const_iterator ConfigFile::find(string const &target) const { return d_ptr->find(target); } bobcat-3.19.01/configfile/destructor.cc0000644000175000017500000000011212222576537016722 0ustar frankfrank#include "configfile.ih" ConfigFile::~ConfigFile() { delete d_ptr; } bobcat-3.19.01/configfile/size.f0000644000175000017500000000010712223023055015321 0ustar frankfrankinline size_t ConfigFile__::size() const { return d_line.size(); } bobcat-3.19.01/configfile/findkey.f0000644000175000017500000000022212223023055015776 0ustar frankfrankinline string ConfigFile__::findKey(string const &keyPattern, size_t count) { return searchFor("^\\s*" + keyPattern + "\\s+(\\S+)", count); } bobcat-3.19.01/configfile/operatorassign2.cc0000644000175000017500000000024412222576537017654 0ustar frankfrank#include "configfile.ih" ConfigFile &ConfigFile::operator=(ConfigFile const &rhs) { ConfigFile tmp(rhs); swap(d_ptr, tmp.d_ptr); return *this; } bobcat-3.19.01/configfile/build0000755000175000017500000003470212223023055015235 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/hostname // script generated by the C++ icmake script version 2.02 string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.fm BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. When defined as an EMPTY STRING, the static library libXXX.a is created: all programs linked to this library will themselves contain the code of the required object modules. This will result in code duplication over different programs linked to this library. When defined as a VERSION STRING, e.g., 1.0.4, a shared library libXXX.so.VERSION is constructed, as well as the links libXXX.so.MAINVERSION and libXXX.so (e.g. 1.0.0 creates libXXX.so.1.0.0, libXXX.so.1 and libXXX.so). Note that with a shared library, the library is always constructed fresh from the compiled object files. But programs linked to this library will SHARE the code stored in the shared library. These programs will therefore tend to be relatively small. Also note that `ldconfig -v' might be required after installing a shared library (libXXX.so) for the first time, so that the linker knows of its existence (in ld.so.cache) BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (default: defined). COMPILER: The compiler to use. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking LOCAL_NAMESPACE:The namespace that you, the programmer, use yourself. USING: List of :-separated namespaces to be used in sources and .fh files, appearing in `using' directives. USING does NOT automatically include LOCAL_NAMESPACE: add your LOCAL_NAMESPACE name to this list if want a `using' directive for your own namespace as well. Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.fm RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ #define BUILD_LIBRARY "" // #define BUILD_PROGRAM #define COMPILER "g++" #define COPT "-Wall --std=c++0x" #define ECHO_REQUEST 1 //#define GDB "-g" #define ICMAKE "/usr/bin/icmake" #define LIBS "" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path libso, // symbolic link to so.major library path libsomajor, // lib.so.major path ofiles, // wildcards for o-files sources, // sources to be used current; // contains name of current dir. int nClasses, // number of classes/subdirectories program, // 1: program is built so_lib; // 1: so_lib is built list classes; // list of classes/directories /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; program = 0; #ifdef BUILD_LIBRARY if (strlen(BUILD_LIBRARY)) so_lib = !program; else so_lib = 0; #else if (!program) { printf("no program, no library ?\n"); exit(1); } #endif if (so_lib) copt += " -fPIC"; cwd = chdir("."); setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY if (!so_lib) // keep all files with so libs files = altered(files, library);// keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* L I N K S O . I M */ void link_solib(string library) { string gdb; #ifdef GDB gdb = GDB; #endif #ifdef BUILD_LIBRARY int index; list sofiles, version; version = strtok(BUILD_LIBRARY, "."); libso = "lib" + library + ".so"; libxxx = libso + "."; libsomajor = libxxx + element(0, version); libxxx += BUILD_LIBRARY; for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir(current); // chdir to a class directory. prefix_class((string)index); chdir(cwd); // go back to parent dir } if (!makelist("o/*.o")) ofiles = "*/o/*.o"; printf("\n"); exec(COMPILER, gdb, "-shared", "-Wl,-soname," + libsomajor, "-o", libxxx, ofiles, libs, "-L.", libpath, lopt ); printf("ok: ", libxxx, "\n"); for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir(current); // chdir to a class directory. rm_class_prefix((string)index); chdir(cwd); // go back to parent dir } exec("ln", "-sf", libxxx, libsomajor); printf("ok: ", libsomajor, "\n"); exec("ln", "-sf", libsomajor, libso); printf("ok: ", libso, "\n"); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int index; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY if (!so_lib) libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { current = element(index, classes); // next class to process chdir(current); // change to directory current = "subdir " + current; std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY if (!so_lib) { // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir } else { link_solib(library); // separate processing for so-lib return; } #endif } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); #ifdef GRAMBUILD libs += " -lfl"; #endif cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); cpp_make ( "", "configfile", // static- or so-library "" ); } bobcat-3.19.01/configfile/reiterator1.cc0000644000175000017500000000020512222576537016770 0ustar frankfrank#include "configfile.ih" RE_iterator::RE_iterator(VsIterVector const &vsIter, size_t idx) : d_vsIter(vsIter), d_idx(idx) {} bobcat-3.19.01/configfile/beginendre2.cc0000644000175000017500000000021712222576537016716 0ustar frankfrank#include "configfile.ih" ConfigFile::RE_iteratorPair ConfigFile::beginEndRE() { return RE_iteratorPair(d_ptr->endRE(), d_ptr->endRE()); } bobcat-3.19.01/configfile/index2.cc0000644000175000017500000000017312222576537015724 0ustar frankfrank#include "configfile.ih" size_t ConfigFile::index(const_iterator const &iterator) { return d_ptr->index(iterator); } bobcat-3.19.01/configfile/casefinder.f0000644000175000017500000000027112223023055016454 0ustar frankfrankinline bool ConfigFile__::casefinder(string const &haystack, string const &needle) { return strcasestr(haystack.c_str(), needle.c_str()) != 0; } bobcat-3.19.01/configfile/index1.f0000644000175000017500000000012112223023055015533 0ustar frankfrankinline size_t ConfigFile__::index(size_t lineNr) { return d_index[lineNr]; } bobcat-3.19.01/configfile/open.cc0000644000175000017500000000131112222576537015467 0ustar frankfrank#include "configfile.ih" void ConfigFile__::open(string const &fname) { ifstream stream; Exception::open(stream, fname); d_line.clear(); // clear the vector d_index.clear(); // clear the line indices d_vsIter.clear(); // clear iterators to matching lines d_re.clear(); // clear a previously set search RE d_rawIndex = 0; // re-initialize the line-index of the // original file string line; while (nextLine(stream, line)) // add the lines to d_line d_line.push_back(line); } void ConfigFile::open(string const &fname) { d_ptr->open(fname); } bobcat-3.19.01/configfile/index1.cc0000644000175000017500000000015012222576537015716 0ustar frankfrank#include "configfile.ih" size_t ConfigFile::index(size_t lineNr) { return d_ptr->index(lineNr); } bobcat-3.19.01/configfile/README0000644000175000017500000000300512223023055015060 0ustar frankfrankAll lines are stored in the vector base class. When StoreIndices was specified the 0-based line indices of lines were stored in d_index. The member open clears the current contents and reinitializes all with the info read from the new file. At construction time comment handling (keep comment / remove comment), case-sensitive searching (sensitive / insensitive) and index storage (store / don't store) can be specified. It can't be modified with the open member, but overloaded assignment is supported and comment and letter case handling can be modified by set-members. The begin() and end() members return the iterators into the vector of configuration file lines (with continuation lines merged, and comment optionally removed). find(target): To find an element `target' in a configuration file find(target) can be used. It it handles case insensitive searches and uses findRE after replacing each character in target by an escape character. This turns the special RE characters into normal characters so findRE can be used fo the matching. findRE(target): here an RE is used to perform the match. It visits alle stored lines of the configuration file returning the first line for which the regular expression matched (using the `match' function in configfile.fh). findKey(key, count): find the value of the `count-th' occurrence of 'key value'. It calls searchFor to find the count-th occurrence of key. findKeyTail acts similarly, but doesn't allow anything to appear beyond value. searchfor(key, pattern, count): bobcat-3.19.01/configfile/opstar.f0000644000175000017500000000013212223023055015655 0ustar frankfrankinline std::string const &RE_iterator::operator*() const { return *d_vsIter[d_idx]; } bobcat-3.19.01/configfile/findkeytail.f0000644000175000017500000000023112223023055016650 0ustar frankfrankinline string ConfigFile__::findKeyTail(string const &keyPattern, size_t count) { return searchFor("^\\s*" + keyPattern + "\\s+(.*)\\s*$", count); } bobcat-3.19.01/configfile/begin.f0000644000175000017500000000013712223023055015436 0ustar frankfrankinline ConfigFile__::const_iterator ConfigFile__::begin() const { return d_line.begin(); } bobcat-3.19.01/configfile/setcommenthandling.f0000644000175000017500000000015012223023055020230 0ustar frankfrankinline void ConfigFile__::setCommentHandling(Comment type) { d_rmComment = type == RemoveComment; } bobcat-3.19.01/configfile/driver/0000755000175000017500000000000012222576537015516 5ustar frankfrankbobcat-3.19.01/configfile/driver/driver.rc0000644000175000017500000000033412222576537017337 0ustar frankfrank# This is comment hello (at idx 1) # void rematch one multiple \ lines (starts at idx 2) another \ \ set of \ lines (starts at idx 4) rematch two # comment only history history-one two bobcat-3.19.01/configfile/driver/build0000755000175000017500000000140012222576537016536 0ustar frankfrank#!/bin/bash ln -sf ../configfile . ln -sf ../configfile.ih . case $1 in (b) rm configfile configfile.ih g++ -DBOBCAT --static --std=c++0x -I../../tmp -o driver driver.cc \ -L../../tmp/lib -lbobcat -s ;; (o) g++ --std=c++0x -o driver *.cc ../tmp/o/*.o -lbobcat -s ;; (c) g++ --std=c++0x -o driver *.cc -lbobcat -s ;; (l) g++ --std=c++0x -o driver *.cc -lconfigfile -lbobcat -L.. -s ;; (*) echo $0 b links to bobcat built by 'build libraries all' echo $0 o links to the files in ../tmp/o echo $0 c links to the files in the current dir only echo $0 l links to \*.cc, ../libconfig.a and std bobcat rm -f driver ;; esac rm -f configfile configfile.ih bobcat-3.19.01/configfile/driver/driver.cc0000644000175000017500000000436612222576537017331 0ustar frankfrank#include #include #include #ifdef BOBCAT #include #else #include "configfile" #endif using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) { cout << "Need name of configfile\n"; return 1; } ConfigFile cf(argv[1], ConfigFile::RemoveComment, ConfigFile::SearchCaseInsensitive, ConfigFile::StoreIndices); cout << "opened: " << argv[1] << '\n'; cout << "Got " << cf.size() << " lines\n"; cf.open(argv[1]); cout << "opened again: " << argv[1] << '\n'; cout << "Got " << cf.size() << " lines\n"; cout << cf[0] << " from line " << cf.index(0) << "\n"; cout << "================\n"; copy(cf.begin(), cf.end(), ostream_iterator(cout, "\n")); while (true) { cout << "Enter literal to search for (or just Enter): "; string param; if (!getline(cin, param) || !param.length()) break; auto it = cf.find(param); if (it != cf.end()) cout << *it << ": at index " << cf.index(it) << endl; else cout << " < not found > " << endl; } while (true) { cout << "Enter RE to search for (or just Enter): "; string param; if (!getline(cin, param) || !param.length()) break; auto it = cf.findRE(param); if (it != cf.end()) cout << *it << ": at index " << cf.index(it) << endl; else cout << " < not found > " << endl; } while (true) { cout << "Finding all lines matching a RE.\n" "Enter the RE (or just Enter): "; string param; if (!getline(cin, param) || !param.length()) return 0; auto iters = cf.beginEndRE(param); cout << "Counting: " << (iters.second - iters.first) << " matches\n"; while (iters.first != iters.second) { cout << *iters.first << endl; ++iters.first; } cout << "value of findKey: " << cf.findKey(param) << '\n'; } } catch (Errno e) { cout << "Fatal: " << e.why() << endl; return 1; } bobcat-3.19.01/configfile/driver/config0000644000175000017500000000074112222576537016710 0ustar frankfrank# these options are also defined by driver.cc option option-value: \#xyz option-value: #xyz # other lines may also be provided, lines starting with # are comment a line not containing an option # this is ignored noline: this one too line: this is found this is not a line containing line: at the beginning of the line line: this one is line: what about this one? \ it's extending over multiple lines and there may, of course, be more lines in this file bobcat-3.19.01/configfile/finder.f0000644000175000017500000000020512223023055015615 0ustar frankfrankinline bool ConfigFile__::finder(string const &haystack, string const &needle) { return haystack.find(needle) != string::npos; } bobcat-3.19.01/configfile/resetvsiter.cc0000644000175000017500000000050212222576537017106 0ustar frankfrank#include "configfile.ih" void ConfigFile__::resetVsIter(string const &re) { d_vsIter.clear(); d_re = re; d_pattern.setPattern(re, d_caseSensitive); for(auto start = begin(), stop = end(); start != stop; ++start) { if (d_pattern << *start) d_vsIter.push_back(start); } } bobcat-3.19.01/configfile/searchfor.cc0000644000175000017500000000113112222576537016502 0ustar frankfrank#include "configfile.ih" // The keyPat *must* have a (...) subexpression, defining what to return string ConfigFile__::searchFor(string const &keyPat, size_t count) { string ret; if (count == 0) throw Exception() << "findKey/-Tail: count must be > 0"; beginRE(keyPat); if (count <= d_vsIter.size()) // at least 'count' lines { // are required d_pattern << *d_vsIter[count - 1]; // if so, return the tail of ret = d_pattern[d_pattern.end() - 1]; // line[count - 1] } return ret; } bobcat-3.19.01/configfile/opsub.f0000644000175000017500000000015312223023055015500 0ustar frankfrankinline int operator-(RE_iterator const &lhs, RE_iterator const &rhs) { return lhs.d_idx - rhs.d_idx; } bobcat-3.19.01/configfile/opneq.f0000644000175000017500000000015012223023055015467 0ustar frankfrankinline bool operator!=(RE_iterator const &lhs, RE_iterator const &rhs) { return not (lhs == rhs); } bobcat-3.19.01/configfile/end.cc0000644000175000017500000000015612222576537015302 0ustar frankfrank#include "configfile.ih" ConfigFile::const_iterator ConfigFile::end() const { return d_ptr->end(); } bobcat-3.19.01/configfile/end.f0000644000175000017500000000013312223023055015114 0ustar frankfrankinline ConfigFile__::const_iterator ConfigFile__::end() const { return d_line.end(); } bobcat-3.19.01/configfile/operatorindex.cc0000644000175000017500000000016412222576537017416 0ustar frankfrank#include "configfile.ih" std::string const &ConfigFile::operator[](size_t idx) const { return (*d_ptr)[idx]; } bobcat-3.19.01/configfile/beginre2.cc0000644000175000017500000000035112222576537016226 0ustar frankfrank#include "configfile.ih" ConfigFile::const_RE_iterator ConfigFile::beginRE(string const &re) { static bool called = false; deprecated__(called, "ConfigFile::beginRE(std::string const &)"); return d_ptr->beginRE(re); } bobcat-3.19.01/configfile/setsearchcasing.cc0000644000175000017500000000016512222576537017702 0ustar frankfrank#include "configfile.ih" void ConfigFile::setSearchCasing(SearchCasing type) { d_ptr->setSearchCasing(type); } bobcat-3.19.01/configfile/rmcommandandescapes.cc0000644000175000017500000000210612222576537020535 0ustar frankfrank#include "configfile.ih" bool ConfigFile__::rmCommentAndEscapes(string &line) { size_t pos = 0; size_t lastBackslash = 0; while (true) { size_t hit; // change \\ to one backslash if ((hit = line.find("\\\\", pos)) != string::npos) line.erase(lastBackslash = hit, 1); else if ((hit = line.find("\\#", pos)) != string::npos) line.replace(hit, 2, "#"); // replace by # else { if ((hit = line.find('#', pos)) != string::npos) { lastBackslash = string::npos; line.erase(hit); // erase comment } if (line.length() > lastBackslash + 1 && *line.rbegin() == '\\') { line.resize(line.length() - 1); return true; } return false; } pos = hit + 1; // try again beyond the // last-checked character } } bobcat-3.19.01/configfile/findkeytail.cc0000644000175000017500000000050012222576540017022 0ustar frankfrank#include "configfile.ih" // findKeyTail("key:") - // trimmed text following key. initial ws before // key should not be specified: skipped by findKeyTail. string ConfigFile::findKeyTail(string const &keyPattern, size_t count) { return d_ptr->findKeyTail(keyPattern, count); } bobcat-3.19.01/configfile/beginre.cc0000644000175000017500000000027112222576540016137 0ustar frankfrank#include "configfile.ih" ConfigFile__::const_RE_iterator ConfigFile__::beginRE(string const &re) { if (re != d_re) resetVsIter(re); return RE_iterator(d_vsIter, 0); } bobcat-3.19.01/configfile/configfile3.cc0000644000175000017500000000017012222576540016712 0ustar frankfrank#include "configfile.ih" ConfigFile::ConfigFile(ConfigFile &&tmp) : d_ptr( new ConfigFile__(move(*tmp.d_ptr) )) {} bobcat-3.19.01/configfile/setcommenthandling.cc0000644000175000017500000000016612222576540020412 0ustar frankfrank#include "configfile.ih" void ConfigFile::setCommentHandling(Comment type) { d_ptr->setCommentHandling(type); } bobcat-3.19.01/configfile/trimleft.cc0000644000175000017500000000040612222576540016352 0ustar frankfrank#include "configfile.ih" void ConfigFile__::trimLeft(string &line) { // remove initial ws. string::size_type pos = line.find_first_not_of(" \t"); if (pos != string::npos) line.erase(0, pos); } bobcat-3.19.01/configfile/endre.cc0000644000175000017500000000030412222576540015616 0ustar frankfrank#include "configfile.ih" ConfigFile::const_RE_iterator ConfigFile::endRE() const { static bool called = false; deprecated__(called, "ConfigFile::endRE()"); return d_ptr->endRE(); } bobcat-3.19.01/configfile/findre.cc0000644000175000017500000000070512222576540015775 0ustar frankfrank#include "configfile.ih" vector::const_iterator ConfigFile__::findRE(string const &re) const { d_pattern.setPattern(re, d_caseSensitive); return find_if( begin(), end(), [&](string const &str) { return d_pattern << str; } ); } vector::const_iterator ConfigFile::findRE(string const &re) const { return d_ptr->findRE(re); } bobcat-3.19.01/configfile/configfile2.cc0000644000175000017500000000075012222576540016715 0ustar frankfrank#include "configfile.ih" ConfigFile__::ConfigFile__(string const &fname, Comment cType, SearchCasing sType, Indices iType) : d_rmComment(cType == RemoveComment), d_caseSensitive(sType == SearchCaseSensitive), d_indices(iType == StoreIndices) { open(fname); } ConfigFile::ConfigFile(string const &fname, Comment cType, SearchCasing sType, Indices iType) : d_ptr(new ConfigFile__(fname, cType, sType, iType)) {} bobcat-3.19.01/configfile/configfile0000644000175000017500000000763212223023055016242 0ustar frankfrank#ifndef INCLUDED_BOBCAT_CONFIGFILE_ #define INCLUDED_BOBCAT_CONFIGFILE_ // Lines are stored with initial WS removed. // If a line ends in \, then the next line (initial WS removed) // is appended to the current line. // Information at and beyond the first # on individual lines is removed // if the rmComment flag is set to true // Then, lines containing only blanks and tabs are not stored #include #include #include namespace FBB { class RE_iterator: public std::iterator { friend class ConfigFile__; friend int operator-(RE_iterator const &lhs, // opneg.f RE_iterator const &rhs); friend bool operator==(RE_iterator const &lhs, RE_iterator const &rhs); // contains iterators to lines matching REs typedef std::vector::const_iterator VsIterator; typedef std::vector VsIterVector; VsIterVector const &d_vsIter; size_t d_idx; public: RE_iterator &operator++(); std::string const &operator*() const; // opstar.f std::string const *operator->() const; // oparrow.f private: RE_iterator(VsIterVector const &vsIter, size_t idx); }; struct CFEnums__ { typedef RE_iterator const_RE_iterator; typedef std::vector::const_iterator const_iterator; typedef std::pair RE_iteratorPair; enum Comment { KeepComment, RemoveComment }; enum SearchCasing { SearchCaseSensitive, SearchCaseInsensitive }; enum Indices { IgnoreIndices, StoreIndices }; }; class ConfigFile__; class ConfigFile: public CFEnums__ { ConfigFile__ *d_ptr; public: explicit ConfigFile(Comment cType = KeepComment, // 1 SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); // 2 explicit ConfigFile(std::string const &fname, // config file name Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices); ConfigFile(ConfigFile &&tmp); // 3 ConfigFile(ConfigFile const &rhs); // 4 ~ConfigFile(); ConfigFile &operator=(ConfigFile &&tmp); ConfigFile &operator=(ConfigFile const &rhs); // 2 void open(std::string const &fname); void setCommentHandling(Comment type); void setSearchCasing(SearchCasing type); const_iterator begin() const; const_iterator end() const; const_RE_iterator beginRE(std::string const &re); // 2, deprecated const_RE_iterator endRE() const; // deprecated RE_iteratorPair beginEndRE(std::string const &re); RE_iteratorPair beginEndRE(); const_iterator find(std::string const &target) const; const_iterator findRE(std::string const &re) const; std::string findKey(std::string const &key, size_t count = 1); std::string findKeyTail(std::string const &key, size_t count = 1); size_t index(size_t lineNr); // 1 size_t index(const_iterator const &iterator); // 2 std::string const &operator[](size_t idx) const; size_t size() const; }; #include "opstar.f" #include "oparrow.f" // Free members: bool operator==(RE_iterator const &lhs, RE_iterator const &rhs); #include "opneq.f" // RE_iterator != RE_iterator #include "opsub.f" // RE_iterator - RE_iterator } // FBB #endif bobcat-3.19.01/configfile/size.cc0000644000175000017500000000013012222576540015470 0ustar frankfrank#include "configfile.ih" size_t ConfigFile::size() const { return d_ptr->size(); } bobcat-3.19.01/configfile/operatorassign.cc0000644000175000017500000000020412222576540017560 0ustar frankfrank#include "configfile.ih" ConfigFile &ConfigFile::operator=(ConfigFile &&tmp) { *d_ptr = move(*tmp.d_ptr); return *this; } bobcat-3.19.01/configfile/setsearchcasing.f0000644000175000017500000000016412223023055017520 0ustar frankfrankinline void ConfigFile__::setSearchCasing(SearchCasing type) { d_caseSensitive = type == SearchCaseSensitive; } bobcat-3.19.01/configfile/opindex.f0000644000175000017500000000014112223023055016013 0ustar frankfrankinline std::string const &ConfigFile__::operator[](size_t idx) const { return d_line[idx]; } bobcat-3.19.01/configfile/findkey.cc0000644000175000017500000000044612222576540016161 0ustar frankfrank#include "configfile.ih" // findKey("key:") - first ws-delimited field following key. initial ws before // key should not be specified: skipped by findKey. string ConfigFile::findKey(string const &keyPattern, size_t count) { return d_ptr->findKey(keyPattern, count); } bobcat-3.19.01/configfile/configfile1.cc0000644000175000017500000000063412222576540016715 0ustar frankfrank#include "configfile.ih" ConfigFile__::ConfigFile__(Comment cType, SearchCasing sType, Indices iType) : d_rmComment(cType == RemoveComment), d_caseSensitive(sType == SearchCaseSensitive), d_indices(iType == StoreIndices) {} ConfigFile::ConfigFile(Comment cType, SearchCasing sType, Indices iType) : d_ptr(new ConfigFile__(cType, sType, iType)) {} bobcat-3.19.01/configfile/operatoreqre.cc0000644000175000017500000000024712222576540017237 0ustar frankfrank#include "configfile.ih" bool FBB::operator==(RE_iterator const &lhs, RE_iterator const &rhs) { return lhs.d_idx == rhs.d_idx && lhs.d_vsIter == rhs.d_vsIter; } bobcat-3.19.01/configfile/trimright.cc0000644000175000017500000000035112222576540016534 0ustar frankfrank#include "configfile.ih" void ConfigFile__::trimRight(string &line, bool appendNext) { if (appendNext) return; size_t pos = line.find_last_not_of(" \t"); if (pos != string::npos) line.resize(pos + 1); } bobcat-3.19.01/configfile/reoperatorinc.cc0000644000175000017500000000014412222576540017377 0ustar frankfrank#include "configfile.ih" RE_iterator &RE_iterator::operator++() { ++d_idx; return *this; } bobcat-3.19.01/configfile/endre.f0000644000175000017500000000017212223023055015446 0ustar frankfrankinline ConfigFile__::const_RE_iterator ConfigFile__::endRE() const { return RE_iterator(d_vsIter, d_vsIter.size()); } bobcat-3.19.01/configfile/index2.f0000644000175000017500000000015612223023055015544 0ustar frankfrankinline size_t ConfigFile__::index(const_iterator const &iterator) { return d_index[iterator - begin()]; } bobcat-3.19.01/configfile/configfile4.cc0000644000175000017500000000016512222576540016717 0ustar frankfrank#include "configfile.ih" ConfigFile::ConfigFile(ConfigFile const &rhs) : d_ptr(new ConfigFile__(*rhs.d_ptr)) {} bobcat-3.19.01/configfile/nextline.cc0000644000175000017500000000072412222576540016355 0ustar frankfrank#include "configfile.ih" bool ConfigFile__::nextLine(istream &inStream, string &dest) { dest.erase(); string line; while (getline(inStream, line)) { ++d_rawIndex; // at the next line trimLeft(line); bool appendNext = rmCommentAndEscapes(line); trimRight(line, appendNext); dest += line; if (not appendNext) return true; } return dest.length(); } bobcat-3.19.01/contrib/0000755000175000017500000000000012222576534013553 5ustar frankfrankbobcat-3.19.01/contrib/c-conf0000755000175000017500000002771112222576534014656 0ustar frankfrank#!/usr/bin/perl use strict; use Getopt::Std; # Globals my $VER = "1.05"; # 1.05 [KK 2006-09-28] Flag -s (silent) implemented. Usage text updated. # 1.04 [KK 2006-09-05] C-compilers: gcc/g++ get selected first, instead of # cc/c++. Helps HP-UX ports. [Thanks, Bernd Krumboeck.] # 1.03 [KK 2006-07-19] 'subfiles' keeps track of visited dirs incase of # recursion. Testing is now by inode, used to be by name. # 1.02 [KK 2006-06-01] 'findbin' searches for .exe too now, for Cygwin support # 1.01 [KK 2005-09-29] Implemented context-sensitive help via -h. # Action 'header' implemented. # 1.00 [KK 2005-09-28] First version # Configuration my @def_headerdirs = ('/usr/include', '/usr/local/include', "$ENV{HOME}/include", ); my @def_libdirs = ('/usr/lib', '/usr/local/lib', '/usr/ucblib', "$ENV{HOME}/lib", ); my @c_compilers = ('gcc', 'cc'); my @cpp_compilers = ('g++', 'c++'); # Globals my %opts; my $base; my @warnings; my $printed; my @headerdirs; my @libdirs; # Show usage and croak sub usage { die <<"ENDUSAGE" This is c-conf, the C compilation configuration helper V$VER Copyright (c) e-tunity. Contact for information. Usage: $base [flags] header FILE.H [FILE.H...] Searches for directories containing the named header(s), returns appropriate -I flags. $base [flags] headerdir DIR [DIR...]: Searches for directory containing headers, returns appropriate -I flags. $base [flags] ifheader FILE.H DEFINE Searches for the named header. If found, a compilation flag -DDEFINE is returned, indicating that the header is found. $base [flags] libfunction FUNC DEFINE Creates a small program that tries to use FUNC. If this succeeds, a -DDEFINE=1 flag is returned. $base [flags] lib NAME [NAME...]: Searches for libNAME.{a,so,...}, returns appropriate -L and -l flags. $base [flags] so-name NAME: Returns filename of a shared-object for NAME, e.g. libNAME.so $base [flags] so-cflags: Returns compilation flags to build shared objects $base [flags] so-lflags: Returns linkage flags to produce a shared-object library $base [flags] c-compiler: Returns name of C compiler $base [flags] c++-compiler: Returns name of C++ compiler Optional flags: -h: to show short help for an action, e.g. try '$base -h so-name' -s: to suppress showing of warnings -v: to show verbose messages -I DIR[,DIR..]: to add DIR(s) to the searchpath for headers, default searchpath is @headerdirs -L DIR[,DIR..]: to add DIR(s) to the searchpath for libraries, default searchpath is @libdirs Meaningful output is returned on stdout. Verbose messages, warnings and errors go to stderr. ENDUSAGE } # Issue a warning sub warning { push (@warnings, "@_"); } # Show a message sub msg { return unless ($opts{v}); print STDERR ("$base: ", @_); } # Show help info if -h was given sub checkhelp { return unless ($opts{h}); print STDERR (@_); exit (1); } # Basename / dirname of a file. sub basename ($) { my $name = shift; $name =~ s{.*/}{}; return ($name); } sub dirname ($) { my $name = shift; return (undef) unless ($name =~ /\//); $name =~ s{/[^/]$}{}; return ($name); } # Get the uname. sub uname() { my $ret = `uname`; chomp ($ret); msg ("uname: $ret\n"); return ($ret); } # Find a binary along the path. sub findbin($) { my $bin = shift; msg ("Looking for executable '$bin'\n"); foreach my $d (split (/:/, $ENV{PATH})) { if (-x "$d/$bin" or -f "$d/bin.exe") { msg ("Found as '$d/$bin'\n"); return ("$d/$bin"); } } msg ("Not found!\n"); } # Recursively determine the files under a given dir. my %_dir_visited; sub subfiles ($$$) { my ($dir, $mask, $recursive) = @_; %_dir_visited = () unless ($recursive); my ($dev, $ino) = stat($dir) or return (undef); my $tag = sprintf ("%d-%d", $dev, $ino); if ($_dir_visited{$tag}) { msg ("Path '$dir' was already visited (as $_dir_visited{$tag})\n"); return (undef); } $_dir_visited{$tag} = $dir; msg ("Scanning for '$mask' under '$dir'\n"); if (! -d $dir) { msg ("Scan path ends, '$dir' is not an accessible directory\n"); return (undef); } my @ret = (); foreach my $f (glob ("$dir/$mask")) { if (-f $f) { push (@ret, $f); msg ("Found a hit as '$f'\n"); } msg ("Hits so far: ", $#ret + 1, "\n") if ($#ret > -1); } foreach my $d (glob ("$dir/*")) { next unless (-d $d); msg ("Recursing from '$dir' into '$d'\n"); my @subret = subfiles ("$d", $mask, 1); my $added = 0; foreach my $f (@subret) { if (-f $f) { push (@ret, $f); $added++; } } msg ("Added ", $added, " hits from '$d'\n") if ($added); } if ($#ret > -1) { msg ("Found ", $#ret + 1, " entries matching '$mask' under '$dir'\n"); return (@ret); } else { # msg ("No entries matching '$mask' under '$dir' found\n"); return (undef); } } # Output stuff sub output { print (' ') if ($printed++); print (@_); } # Find a header, output a define if found. sub if_header { checkhelp <<"ENDHELP"; 'ifheader' tries to find a header file in the 'include' directories. When found, a define-flag for the C compiler is returned. E.g.: $base ifheader malloc.h HAVE_MALLOC_H (may return -DHAVE_MALLOC_H) Use in a Makefile as in: CFLAGS = \$(CFLAGS) \$(shell c-conf ifheader malloc.h HAVE_MALLOC_H Then in a C source as: #ifdef HAVE_MALLOC_H #include #endif ENDHELP usage() if ($#_ != 1); my ($h, $def) = @_; msg ("Looking for '$h'\n"); foreach my $d (@headerdirs) { if (-f "$d/$h") { output ("-D$def"); return; } } } # Find a header sub header { checkhelp <<"ENDHELP"; 'header' locates one or more C headers in the 'include' directories. E.g.: $base header e-lib.h stdio.h (may return -I/usr/include -I/usr/e/include) Use in a Makefile as in: CFLAGS = -C -Wall \$(shell c-conf header e-lib.h) Then in a C source as: #include ENDHELP usage() if ($#_ == -1); foreach my $h (@_) { msg ("Looking for '$h'\n"); my $found = 0; foreach my $d (@headerdirs) { msg ("Trying '$d/$h'\n"); if (-f "$d/$h") { $found++; msg ("Found\n"); output ("-I$d"); last; } } warning ("Failed to locate header '$h' in @headerdirs\n") unless ($found); } } # Find a header directory sub headerdir { checkhelp <<"ENDHELP"; 'headerdir' locates directories under which (in steps) C headers are E.g.: $base headerdir libxml2 (may return '-I/usr/include/libxml2') Use in a Makefile as in: CFLAGS = -C -Wall \$(shell c-conf headerdir libxml2) Then in a C source as: #include ENDHELP usage() if ($#_ == -1); foreach my $headerdir (@_) { msg ("Looking for header dir '$headerdir'\n"); my $found = 0; foreach my $d (@headerdirs) { msg ("Trying as '$d/$headerdir'\n"); my $target = "$d/$headerdir"; if (subfiles ($target, '*.h', 0)) { output ("-I$target"); $found++; } } warning ("Header dir '$headerdir' not found\n") unless ($found); } } # Find a library sub lib { checkhelp <<"ENDHELP"; 'lib' generates the linkage flags for a given library name. The name is bare, without 'lib' and '.so' and the like. E.g.: $base lib xml2 (may return '-L/usr/lib -lxml2') Use in a Makefile as in: LDFLAGS = \$(shell c-conf lib xml2) ENDHELP usage() if ($#_ == -1); foreach my $lib (@_) { msg ("Looking for lib '$lib'\n"); my $found = 0; foreach my $d (@libdirs) { msg ("Trying under '$d'\n"); my $hit = (subfiles ($d, "lib$lib.*", 0))[0]; if ($hit) { msg ("Found as '$hit'\n"); $found++; $hit =~ s{/[^/]*$}{}; output ("-L$hit -l$lib"); } } warning ("Library '$lib' not found\n") unless ($found); } } # Compilation flags to make a so-ready object. sub so_cflags { checkhelp <<"ENDHELP"; 'so-cflags' returns the compilation flags that are necessary when building objects for a shared library. E.g.: $base so-cflags (may return '-fPIC') Use in a Makefile as in: CFLAGS = -c -g -Wall \$(shell c-conf so-cflags) ENDHELP usage() if ($#_ > -1); if (uname() eq 'Darwin') { output ('-fPIC'); } elsif (uname() eq 'Linux') { output ('-fpic'); } } # Linkage flags to make an so. sub so_lflags { checkhelp << "ENDHELP"; 'so-lflags' returns the linkage flags that are necessary when combining objects into a shared library. E.g.: $base so-lflags (may return '-dynamiclib -Wl,-single_module') Use in a Makefile as in: MY_SO = \$(shell c-conf so-name my) \$(MY_SO): *.o \$(CC) -o \$(MY_SO) \$(shell c-conf so-lflags) *.o ENDHELP usage() if ($#_ > -1); my $lib = shift; if (uname() eq 'Darwin') { output ("-dynamiclib -Wl,-single_module"); } else { output ("-shared"); } } # Get the C compiler sub c_compiler { checkhelp <<"ENDHELP"; 'c-compiler' tries to find a C compiler and returns its (bare) name. E.g.: $base c-compiler -> gcc ENDHELP usage() if ($#_ > -1); foreach my $c (@c_compilers) { if (findbin ($c)) { output ($c); return; } } warning ("No C compiler found\n"); } # Get the C++ compiler sub cpp_compiler { checkhelp <<"ENDHELP"; 'c++-compiler' tries to find a C++ compiler and returns its (bare) name. E.g.: $base c++-compiler -> g++ ENDHELP usage() if ($#_ > -1); foreach my $c (@cpp_compilers) { if (findbin ($c)) { output ($c); return; } } warning ("No C++ compiler found\n"); } # Get the name for an SO. sub so_name { checkhelp <<"ENDHELP"; 'so-name' returns the filename of a shared library, based on the LIB argument. E.g.: $base so-name test -> libtest.so ENDHELP usage() if ($#_ != 0); my $name = shift; my $dir = dirname ($name); my $base = basename ($name); my $dest; if (uname() eq 'Darwin') { $dest = "lib$base.dylib"; } else { $dest = "lib$base.so"; } if ($dir ne '') { output ("$dir/$dest"); } else { output ("$dest"); } } # Check that a libfunction is present. sub libfunction { checkhelp <<"ENDHELP"; 'libfunction' checks whether a library function is present. There are two arguments: the function to check, and a define to output when the function is found. The output is a -D flag for the compiler commandline. E.g.: $base libfunction printf HAVE_PRINTF -> -DHAVE_PRINTF=1 $base libfunction foo_bar HAVE_FOOBAR -> (nothing) ENDHELP usage() if ($#_ != 1); my ($func, $def) = @_; # Create a temp .c file. my $src = "/tmp/$$.c"; my $dst = "/tmp/$$.out"; open (my $of, ">$src") or die ("Cannot write $src: $!\n"); print $of ("main () {\n", " void $func (void);\n", " $func();\n", "}\n"); close ($of); my $cc; foreach my $c (@c_compilers) { if (findbin ($c)) { $cc = $c; last; } } die ("Failed to locate C compiler\n") if ($cc eq ''); my $ret = system ("$cc -o $dst $src >/dev/null 2>&1"); unlink ($src, $dst); output ("-D$def=1") if ($ret == 0); } # Main starts here $base = $0; $base =~ s{.*/}{}; usage () unless (getopts ('vhI:L:s', \%opts)); foreach my $d (split (/,/, $opts{L})) { push (@libdirs, $d); } foreach my $d (split (/,/, $opts{I})) { push (@headerdirs, $d); } push (@libdirs, @def_libdirs); push (@headerdirs, @def_headerdirs); my $action = shift (@ARGV); if ($action eq 'header') { header (@ARGV); } elsif ($action eq 'headerdir') { headerdir (@ARGV); } elsif ($action eq 'lib') { lib (@ARGV); } elsif ($action eq 'so-cflags') { so_cflags (@ARGV); } elsif ($action eq 'so-lflags') { so_lflags (@ARGV); } elsif ($action eq 'c-compiler') { c_compiler(@ARGV); } elsif ($action eq 'c++-compiler') { cpp_compiler(@ARGV); } elsif ($action eq 'so-name') { so_name (@ARGV); } elsif ($action eq 'ifheader') { if_header (@ARGV); } elsif ($action eq 'libfunction') { libfunction (@ARGV); } else { usage (); } print ("\n") if ($printed); if ($#warnings > -1) { foreach my $w (@warnings) { print STDERR ("$base WARNING: $w") unless ($opts{s}); } exit (1); } exit (0); bobcat-3.19.01/datetime/0000755000175000017500000000000012242431634013700 5ustar frankfrankbobcat-3.19.01/datetime/updatetime.cc0000644000175000017500000000115012222576533016353 0ustar frankfrank#include "datetime.ih" bool DateTime::updateTime(TimeStruct &tm) { if (!d_ok) return false; time_t utcSec = d_utcSec; TimeStruct dtm = d_tm; int dspShift = d_displayZoneShift; // this also allows for DST d_tm = tm; d_tm.tm_sec -= dspShift; // tm back to UTC d_tm2d_tm(dspShift / 60); // add the display shift for loc. time if (d_ok) { if (dstCorrection()) d_tm.tm_isdst = 1; d_dstShift = 0; } else { d_utcSec = utcSec; d_tm = dtm; d_displayZoneShift = dspShift; } return d_ok; } bobcat-3.19.01/datetime/setmonth2.cc0000644000175000017500000000027212222576533016141 0ustar frankfrank#include "datetime.ih" #include using namespace std; bool DateTime::setMonth(int month) { TimeStruct ts = d_tm; ts.tm_mon = month; return updateTime(ts); } bobcat-3.19.01/datetime/hours.f0000644000175000017500000000010312223023055015172 0ustar frankfrankinline size_t DateTime::hours() const { return d_tm.tm_hour; } bobcat-3.19.01/datetime/datetime4.cc0000644000175000017500000000036112222576533016075 0ustar frankfrank#include "datetime.ih" DateTime::DateTime(time_t time, int displayZoneShift) : d_type(LOCALTIME), d_utcSec(time), d_dstShift(0) { setDisplayZone(zoneShiftSeconds(displayZoneShift)); utcSec2timeStruct(&d_tm, d_utcSec); } bobcat-3.19.01/datetime/opgeq.f0000644000175000017500000000016712223023055015157 0ustar frankfrankinline bool operator>=(DateTime const &left, DateTime const &right) { return left.d_utcSec >= right.d_utcSec; } bobcat-3.19.01/datetime/sethours.cc0000644000175000017500000000062012222576533016067 0ustar frankfrank#include "datetime.ih" // since localtime() and mktime() return each other's inverses, use // localtime() to determine the new # seconds. bool DateTime::setHours(int hours) { TimeStruct ts = d_tm; // d_tm represents the time as displayed // in the current display zone shift ts.tm_hour = hours; // update the hour value return updateTime(ts); } bobcat-3.19.01/datetime/datetime8.cc0000644000175000017500000000040412222576533016077 0ustar frankfrank#include "datetime.ih" DateTime::DateTime(string const &timeStr, int displayZoneShift) : d_type(LOCALTIME) { istringstream in(timeStr); parse(in); // determine timestruct representing hour in UTC d_tm2d_tm(displayZoneShift); } bobcat-3.19.01/datetime/operatorminusis.cc0000644000175000017500000000053612222576533017464 0ustar frankfrank#include "datetime.ih" DateTime &DateTime::operator-=(TimeStruct const &fields) { TimeStruct ts = d_tm; ts.tm_sec -= fields.tm_sec; ts.tm_min -= fields.tm_min; ts.tm_hour -= fields.tm_hour; ts.tm_mday -= fields.tm_mday; ts.tm_mon -= fields.tm_mon; ts.tm_year -= fields.tm_year; updateTime(ts); return *this; } bobcat-3.19.01/datetime/dst.f0000644000175000017500000000014312223023055014630 0ustar frankfrankinline DateTime::TriVal DateTime::dst() const { return static_cast(d_tm.tm_isdst); } bobcat-3.19.01/datetime/zoneshiftseconds.f0000644000175000017500000000016112223023055017426 0ustar frankfrankinline int DateTime::zoneShiftSeconds(int shiftMinutes) { return shiftMinutes / 30 * 30 % (12 * 60) * 60; } bobcat-3.19.01/datetime/dtm2dtm.cc0000644000175000017500000000046612222576533015576 0ustar frankfrank#include "datetime.ih" void DateTime::d_tm2d_tm(int displayZoneShift) // shift in minutes { d_dstShift = 0; d_tm.tm_isdst = 0; d_tm2utcSec(); // UTC seconds matching d_tm in d_utcSec setDisplayZone(zoneShiftSeconds(displayZoneShift)); utcSec2timeStruct(&d_tm, d_utcSec); } bobcat-3.19.01/datetime/operatorinsert.cc0000644000175000017500000000060012222576533017271 0ustar frankfrank#include "datetime.ih" // "Wed Jun 30 21:49:08 1993\n" // 0 ^ // 24 namespace FBB { std::ostream &operator<<(std::ostream &out, DateTime const &dt) { char buf[26]; // Magical number provided by ctime's man-page asctime_r(&dt.d_tm, buf); buf[24] = 0; // remove final \n return out << buf; } } bobcat-3.19.01/datetime/valid.f0000644000175000017500000000007112223023055015135 0ustar frankfrankinline bool DateTime::valid() const { return d_ok; } bobcat-3.19.01/datetime/dtm2utcsec.cc0000644000175000017500000000021512222576533016270 0ustar frankfrank#include "datetime.ih" void DateTime::d_tm2utcSec() { d_utcSec = timeStruct2utcSec(&d_tm); d_utcSec += defaultDisplayZoneShift(); } bobcat-3.19.01/datetime/datetime7dep.cc0000644000175000017500000000130012222576533016563 0ustar frankfrank#include "datetime.ih" DateTime::DateTime(string const &timeStr, TimeType type, int) : d_type(type), d_displayZoneShift(0), d_dstShift(0) { static bool warned = false; if (!warned) { warned = true; cerr << "\n" "Warning: DateTime(string const &timeStr, TimeType type, " "int utcZoneShift)\n" " This constructor is deprecated and is replaced by:\n" " DateTime(string const &timeStr, TimeType type)\n"; } istringstream in(timeStr); parse(in); // determine timestruct representing hour in UTC d_tm2timeType(); } bobcat-3.19.01/datetime/time.f0000644000175000017500000000007612223023055015001 0ustar frankfrankinline time_t DateTime::time() const { return d_utcSec; } bobcat-3.19.01/datetime/datetime3.cc0000644000175000017500000000037612222576533016102 0ustar frankfrank#include "datetime.ih" // time represents UTC or LOCALTIME // For time == LOCALTIME: LOCALTIME = UTC + TZ + dst -> UTC = time - TZ - dst DateTime::DateTime(time_t time, TimeType type) : d_type(type), d_utcSec(time) { displayShift2d_tm(); } bobcat-3.19.01/datetime/setvalid.f0000644000175000017500000000006612223023055015655 0ustar frankfrankinline void DateTime::setValid() { d_ok = true; } bobcat-3.19.01/datetime/settime.cc0000644000175000017500000000063712222576533015675 0ustar frankfrank#include "datetime.ih" bool DateTime::setTime(time_t seconds) { time_t utc = d_utcSec; TimeStruct ts = d_tm; d_utcSec = seconds; if (d_type == UTC) displayShift2d_tm(); else { d_dstShift = 0; d_utcSec -= d_displayZoneShift; utcSec2timeStruct(&d_tm, d_utcSec); } if (!d_ok) { d_utcSec = utc; d_tm = ts; } return d_ok; } bobcat-3.19.01/datetime/localtime.f0000644000175000017500000000011512223023055016006 0ustar frankfrankinline DateTime DateTime::localTime() const { return to(LOCALTIME); } bobcat-3.19.01/datetime/setdisplayzone.cc0000644000175000017500000000023012222576533017265 0ustar frankfrank#include "datetime.ih" void DateTime::setDisplayZone(time_t displayZoneShift) { d_displayZoneShift = (d_type == UTC) ? 0 : displayZoneShift; } bobcat-3.19.01/datetime/timestruct.f0000644000175000017500000000011312223023055016236 0ustar frankfrankinline struct tm const *DateTime::timeStruct() const { return &d_tm; } bobcat-3.19.01/datetime/setfields.cc0000644000175000017500000000077012222576533016203 0ustar frankfrank#include "datetime.ih" bool DateTime::setFields(TimeStruct const &time, int fields) { TimeStruct ts = d_tm; if (fields & SECONDS) ts.tm_sec = time.tm_sec; if (fields & MINUTES) ts.tm_min = time.tm_min; if (fields & HOURS) ts.tm_hour = time.tm_hour; if (fields & MONTHDAY) ts.tm_mday = time.tm_mday; if (fields & MONTH) ts.tm_mon = time.tm_mon; if (fields & YEAR) ts.tm_year = time.tm_year; return updateTime(ts); } bobcat-3.19.01/datetime/datetime5.cc0000644000175000017500000000047712222576533016106 0ustar frankfrank#include "datetime.ih" // struct tm ts = {0, 0, 10, 5, 6, 109, 0, 0, 1}; // dst and day-of-year fields ignored. With UTC ts represents UTC time // with LOCALTIME ts represents local time DateTime::DateTime(TimeStruct const &ts, TimeType type) : d_type(type) { d_tm = ts; d_tm2timeType(); } bobcat-3.19.01/datetime/setday.cc0000644000175000017500000000023112222576533015502 0ustar frankfrank#include "datetime.ih" bool DateTime::setDay(int day) { struct tm tmStruct = d_tm; tmStruct.tm_mday = day; return updateTime(tmStruct); } bobcat-3.19.01/datetime/utc.f0000644000175000017500000000010112223023055014623 0ustar frankfrankinline DateTime DateTime::utc() const { return to(UTC); } bobcat-3.19.01/datetime/dstcorrection.cc0000644000175000017500000000051412222576533017077 0ustar frankfrank#include "datetime.ih" int DateTime::dstCorrection() { if (d_type == UTC) return d_dstShift = 0; bool ok; d_dstShift = dstCorrection(&ok); if (!ok) { // localtime returns dst info d_errno = errno; d_ok = false; } return d_dstShift; } bobcat-3.19.01/datetime/timestr.cc0000644000175000017500000000034212222576533015703 0ustar frankfrank#include "datetime.ih" ostream &DateTime::timeStr(ostream &out) const { return out << setw(2) << d_tm.tm_hour << ':' << setw(2) << d_tm.tm_min << ':' << setw(2) << d_tm.tm_sec; } bobcat-3.19.01/datetime/datetime6.cc0000644000175000017500000000052012222576533016074 0ustar frankfrank#include "datetime.ih" // struct tm ts = {0, 0, 10, 5, 6, 109, 0, 0, 1}; // dst and day-of-year fields ignored. // ts represents UTC, displayZoneShift is added to obtain local time DateTime::DateTime(TimeStruct const &ts, int displayZoneShift) : d_type(LOCALTIME) { d_tm = ts; d_tm2d_tm(displayZoneShift); } bobcat-3.19.01/datetime/opbool.f0000644000175000017500000000007412223023055015333 0ustar frankfrankinline DateTime::operator bool() const { return d_ok; } bobcat-3.19.01/datetime/datetime0000644000175000017500000002177112223023055015420 0ustar frankfrank#ifndef INCLUDED_BOBCAT_DATETIME_ #define INCLUDED_BOBCAT_DATETIME_ #include #include namespace FBB { class DateTime { typedef struct tm TimeStruct; friend std::ostream &operator<<(std::ostream &str, DateTime const &dt); friend std::istream &operator>>(std::istream &str, DateTime &dt); friend bool operator==(DateTime const &left, DateTime const &right); friend bool operator!=(DateTime const &left, DateTime const &right); friend bool operator<(DateTime const &left, DateTime const &right); friend bool operator<=(DateTime const &left, DateTime const &right); friend bool operator>(DateTime const &left, DateTime const &right); friend bool operator>=(DateTime const &left, DateTime const &right); public: enum TimeType { LOCALTIME, UTC }; enum Month { JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER, }; enum Relative { THIS_YEAR, LAST, NEXT, THIS_WEEK, }; enum Weekday { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, }; enum TriVal { UNKNOWN = -1, NO, YES }; enum TimeFields { SECONDS = 1 << 0, MINUTES = 1 << 1, HOURS = 1 << 2, MONTHDAY = 1 << 3, MONTH = 1 << 4, YEAR = 1 << 5 }; private: TimeType d_type; // current type of info in d_tm member // (LOCALTIME (implied when using displayZone) // or UTC) time_t d_utcSec; // time in seconds (UTC) time_t d_displayZoneShift; // correction to UTC when displaying // times // this takes care of dst as well. int d_dstShift; // 3600 or 0: add to displayZoneShift TimeStruct d_tm; // time's elements bool d_ok; size_t d_errno; static char const *s_month[]; static char const *s_day[]; public: explicit DateTime(TimeType type = UTC); // 1. time displayed as // TimeType // shifts in minutes explicit DateTime(int tzShift); // 2. LOCALTIME: // UTC + // tzShift (= TZ + DST) // 3. specify UTC/LOCAL time in DateTime(time_t time, TimeType type); // seconds // 4. LOCALTIME: time (UTC) + DateTime(time_t time, int tzShift); // tzShift (= TZ + DST) // with TimeStruct tm constructor arguments dst, day of the year, // day of the week are ignored: // 5. specify tm fields as // either UTC or LOCALTIME // using the default // tzShift DateTime(TimeStruct const &tm, TimeType type = UTC); // 6. specify UTC tm fields // display + tzShift DateTime(TimeStruct const &tm, int tzShift); // 7. specify UTC/LOCAL text // time explicit DateTime(std::string const &timeStr, TimeType type = UTC); // 7dep. Deprecated. Avoid DateTime(std::string const &timeStr, TimeType type, int); // 8. specify UTC text time // display + // displayZoneShift DateTime(std::string const &timeStr, int tzShift); // 8dep.: Deprecated: avoid DateTime(std::string const &timeStr, int displayZoneShift, int); DateTime &operator+=(time_t seconds); // 1. DateTime &operator+=(TimeStruct const &tm); // 2. DateTime &operator-=(time_t seconds); // opsubis1.f DateTime &operator-=(TimeStruct const &tm); operator bool() const; // opbool.f bool setDay(int day); // 'int' values may be negative or bool setHours(int hours); // postive. bool setMinutes(int minutes); bool setMonth(Month month, Relative where = THIS_YEAR); bool setMonth(int month); // set month, using 0: january this yr // correct for overflows. bool setSeconds(int seconds); bool setTime(time_t time); // utc time bool setWeekday(Weekday weekday, Relative where = NEXT); bool setYear(size_t year); bool setFields(TimeStruct const &tmStruct, int fields); void setValid(); // .f int displayZoneShift() const; // .f TriVal dst() const; // .f size_t error() const; // .f size_t hours() const; // .f size_t minutes() const; // .f Month month() const; // .f size_t monthDayNr() const; // .f std::string rfc2822() const; std::string rfc3339() const; size_t seconds() const; // .f time_t time() const; // .f TimeStruct const *timeStruct() const; bool valid() const; // .f Weekday weekday() const; // .f size_t year() const; // .f size_t yearDay() const; // starts counting at 0 .f size_t yearDayNr() const; // starts counting at 1 .f size_t weekNr() const; // starts counting at 1 DateTime utc() const; // .f DateTime localTime() const; // .f DateTime to(TimeType type) const; DateTime timeZoneShift(int displayZoneShift) const; // .f private: // used by constructors void d_tm2d_tm(int displayZoneShift); // cons 6, 8 void d_tm2timeType(); // cons 5, 7 void d_tm2utcSec(); void displayShift2d_tm(); bool updateTime(TimeStruct &tm); void setDisplayZone(time_t displayZoneShift); void parse(std::istream &in); void parseFromDayName(std::istream &in); std::ostream &timeStr(std::ostream &out) const; time_t timeStruct2utcSec(TimeStruct *ts); // sets d_ok void utcSec2timeStruct(TimeStruct *ts, // sets d_ok .f time_t time); int dstCorrection(bool *ok) const; int dstCorrection(); time_t defaultDisplayZoneShift() const; // seconds static int zoneShiftSeconds(int shiftMinutes); // .f // shifts multiples of 30' // at most +/-12 hours away }; #include "displayzoneshift.f" #include "dst.f" #include "error.f" #include "hours.f" #include "localtime.f" #include "minutes.f" #include "month.f" #include "monthdaynr.f" #include "opbool.f" #include "opsubis1.f" #include "seconds.f" #include "setvalid.f" #include "time.f" #include "timezoneshift.f" #include "utc.f" #include "valid.f" #include "weekday.f" #include "year.f" #include "yearday.f" #include "yeardaynr.f" // Free functions #include "opadd1.f" // DateTime + time_t #include "opadd2.f" // DateTime + tm #include "opeq.f" // DateTime == DateTime #include "opgeq.f" // DateTime >= DateTime #include "opgreater.f" // DateTime > DateTime #include "opleq.f" // DateTime <= DateTime #include "opless.f" // DateTime < DateTime #include "opneq.f" // DateTime != DateTime #include "opsub1.f" // DateTime - time_t #include "opsub2.f" // DateTime - tm } // FBB #endif bobcat-3.19.01/datetime/operatorplusis1.cc0000644000175000017500000000023612222576533017372 0ustar frankfrank#include "datetime.ih" DateTime &DateTime::operator+=(time_t seconds) { d_utcSec += seconds; utcSec2timeStruct(&d_tm, d_utcSec); return *this; } bobcat-3.19.01/datetime/displayshift2dtm.cc0000644000175000017500000000052112222576533017505 0ustar frankfrank#include "datetime.ih" void DateTime::displayShift2d_tm() { if (d_type == UTC) { d_dstShift = 0; setDisplayZone(0); } else { time_t shift = defaultDisplayZoneShift() + dstCorrection(); d_utcSec -= shift; setDisplayZone(shift); } utcSec2timeStruct(&d_tm, d_utcSec); } bobcat-3.19.01/datetime/utcsec2timestruct.cc0000644000175000017500000000034612222576533017714 0ustar frankfrank#include "datetime.ih" void DateTime::utcSec2timeStruct(TimeStruct *ts, time_t time) { time += d_displayZoneShift; // add local time shift (if any) d_ok = gmtime_r(&time, ts); ts->tm_isdst = d_dstShift != 0; } bobcat-3.19.01/datetime/parsefromdayname.cc0000644000175000017500000000170112222576533017551 0ustar frankfrank#include "datetime.ih" void DateTime::parseFromDayName(istream &in) { in.clear(); // Sun Nov 2 13:29:11 2008 - asctime() // Sun Jul 5 23:06:10 CEST 2009 - date(1) // Sun, 05 Jul 2009 23:06:25 +0200 - date(1) -R string day; string mon; in >> day; bool date_R = day.find(',') != string::npos; if (date_R) in >> d_tm.tm_mday >> mon >> d_tm.tm_year; else in >> mon >> d_tm.tm_mday; d_tm.tm_mon = find(s_month, s_month + 12, mon) - s_month; char sep; in >> d_tm.tm_hour >> sep >> d_tm.tm_min >> sep >> d_tm.tm_sec; if (date_R) { in.ignore(6); return; } if (!(in >> d_tm.tm_year)) { in.clear(); // extract TZ name first string tzName; in >> tzName >> d_tm.tm_year; } // called from parse(); parse() subtracts 1900 from tm_year } bobcat-3.19.01/datetime/operatorextract.cc0000644000175000017500000000057712222576533017454 0ustar frankfrank#include "datetime.ih" namespace FBB { std::istream &operator>>(std::istream &in, DateTime &dt) { DateTime::TimeStruct timeStruct = dt.d_tm; time_t time = dt.d_utcSec; dt.parse(in); dt.utcSec2timeStruct(&dt.d_tm, dt.d_utcSec); if (!dt.d_ok) { dt.d_utcSec = time; dt.d_tm = timeStruct; dt.d_ok = false; } return in; } } bobcat-3.19.01/datetime/opsub2.f0000644000175000017500000000022712223023055015253 0ustar frankfrankinline DateTime operator-(DateTime const &left, // d_type tm const &right) { return DateTime(left) -= right; } bobcat-3.19.01/datetime/rfc2822.cc0000644000175000017500000000101312222576533015300 0ustar frankfrank#include "datetime.ih" string DateTime::rfc2822() const { ostringstream out; out << s_day[d_tm.tm_wday] << ", " << setfill('0') << setw(2) << d_tm.tm_mday << ' ' << s_month[d_tm.tm_mon] << ' ' << 1900 + d_tm.tm_year << ' '; timeStr(out) << ' ' << showpos << setw(3) << internal << d_displayZoneShift / 3600 << noshowpos << setw(2) << abs(d_displayZoneShift) % 3600 / 60; return out.str(); } bobcat-3.19.01/datetime/README0000644000175000017500000000172712222576533014575 0ustar frankfranksetDisplayZone - sets the seconds d_displayZoneShift wrt UTC. Argument must allow for TZ and DST shifts. utcSec2timeStruct - receives a *TimeStruct and a time in UTC sets the TimeStruct's tm_isdst flag if the current object's d_dstShift is unequal to zero. dstCorrection - returns 3600 if the current time has DST, based on the computer's locattime computation given UTC sec. returns 0 otherwise. updateTime - called when a time field (day, seconds, year, fields, etc) is updated. Sanitizes the fields (day 32 -> next month, etc) d_tm2d_tm - receives (TZ + DST) shift in minutes, d_tm2utcsec - assigns UTC seconds matching d_tm to d_utcSec zoneShiftSeconds - receives zone shift in minutes, returns shift in seconds, based on TZ shifts being multiples of 30 minutes. bobcat-3.19.01/datetime/error.f0000644000175000017500000000007612223023055015174 0ustar frankfrankinline size_t DateTime::error() const { return d_errno; } bobcat-3.19.01/datetime/opless.f0000644000175000017500000000016512223023055015347 0ustar frankfrankinline bool operator<(DateTime const &left, DateTime const &right) { return left.d_utcSec < right.d_utcSec; } bobcat-3.19.01/datetime/dstcorrection2.cc0000644000175000017500000000051112222576533017156 0ustar frankfrank#include "datetime.ih" int DateTime::dstCorrection(bool *ok) const { TimeStruct ts; tzset(); // see the localtime_r manpage: tzset() required TimeStruct *ret = localtime_r(&d_utcSec, &ts); if (not (*ok = ret)) // 0: can't compute return 0; return ts.tm_isdst == 1 ? 3600 : 0; } bobcat-3.19.01/datetime/displayzoneshift.f0000644000175000017500000000012112223023055017431 0ustar frankfrankinline int DateTime::displayZoneShift() const { return d_displayZoneShift; } bobcat-3.19.01/datetime/driver/0000755000175000017500000000000012222576533015201 5ustar frankfrankbobcat-3.19.01/datetime/driver/build0000755000175000017500000000053212222576533016226 0ustar frankfrank#!/bin/bash # CMD="g++ --std=c++0x -o driver -Wall -I../ driver.cc -L../tmp -ldatetime -L../../tmp/lib -lbobcat -s" CMD="g++ --std=c++0x -o driver -Wall -I../ driver.cc -L../tmp -ldatetime -lbobcat -s" # CMD="g++ -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib -lbobcat -s" #CMD="g++ -o driver -Wall *.cc -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/datetime/driver/driver.cc0000644000175000017500000001417012222576533017006 0ustar frankfrank#include #include #include #include "../datetime" using namespace std; using namespace FBB; int main() { DateTime dt; // Current UTC time cout << " 1: " << dt << " (UTC Time)\n"; DateTime local(DateTime::LOCALTIME); // Current local time cout << " 2: " << local << " (Local Time (LT))\n" " Y: " << local.year() << " M: " << local.month() << " D: " << local.monthDayNr() << "\n" " H: " << local.hours() << " M: " << local.minutes() << " S: " << local.seconds() << "\n" " zoneshift: " << local.displayZoneShift() << " weekday: " << local.weekday() << "\n" " yrDay: " << local.yearDay() << " yrDayNr: " << local.yearDayNr() << " weekNr: " << local.weekNr() << endl; DateTime pst(-8 * 60); // Current PST cout << " 3: " << pst << " (Current PST)\n"; // current local time DateTime modify(dt.time(), DateTime::LOCALTIME); cout << " 4: " << modify << " (Local time now equal to earlier UTC)\n"; cout << " " << modify.utc() << " (matching UTC time)\n"; cout << modify.dst() << endl; modify.setDay(1); // 1st of this month cout << " 5: " << modify << " (LT at 1st of month)\n"; cout << " DST active: " << modify.dst() << endl; modify.setHours(25); // 01:xx.yy, 2nd of this month cout << " 6: " << modify << " (previous LT at 2nd of month 01:xx;yy)\n"; cout << " DST active: " << modify.dst() << endl; modify.setMinutes(00); // 01:00.yy, 2nd of this month cout << " 7: " << modify << " (prev. LT at 00 min.)\n"; cout << " DST active: " << modify.dst() << endl; // 01:00.yy, 2nd of Jan. next year modify.setMonth(DateTime::JANUARY, DateTime::NEXT); cout << " 8: " << modify << " (prev. LT at jan next yr)\n"; cout << " DST active: " << modify.dst() << endl; modify.setMonth(-12); // 01:00.yy, 2nd of Jan. this year cout << " 9: " << modify << " (prev. LT at jan this yr\n"; modify.setSeconds(90); // 01:01.30, 2nd of Jan. this year cout << "10: " << modify << " (prev. LT at hh:01:30)\n"; modify.setTime(dt.time()); // back to current time cout << "11: " << modify << " (LT again)\n"; modify.setWeekday(DateTime::MONDAY); // coming Monday cout << "12: " << modify << " (LT next monday (or now's monday))\n"; modify.setYear(2000); // some years ago cout << "13: " << modify << " (LT at 2000)\n"; struct tm timeStruct = *local.timeStruct(); modify.setFields(timeStruct, 0xff); // use all fields modify = modify.utc(); cout << "14: " << modify << " (UTC via LT in timeStruct)\n"; DateTime local2(timeStruct, DateTime::LOCALTIME); // local time cout << "15: " << local2 << " (LT again)\n"; DateTime local3(timeStruct, 2 * 60); cout << "16: " << local3 << " (LT + 2 hours)\n"; cout << "\n" "Using UTC time string `Tue Nov 18 15:06:29 2008'\n"; DateTime utcStr("Tue Nov 18 15:06:29 2008"); // LT string cout << "17: " << utcStr << " " << utcStr.time() << " (UTC timestring)\n"; DateTime utcX(utcStr.time(), DateTime::UTC); cout << "18: " << utcX << " " << utcX.time() << " (same)\n"; DateTime localStr("Tue Nov 18 15:06:29 2008", DateTime::LOCALTIME); cout << "19: " << localStr << " (creating LT)\n"; DateTime localStr2("Tue Nov 18 15:06:29 2008", DateTime::LOCALTIME, +60); cout << "20: " << localStr2 << " (creating LT + 1 hr (== UTC + 2 hr))\n"; DateTime timeStr3("Tue Nov 18 15:06:29 2008", 120, 60); cout << "21: " << timeStr3 << " (creating UTC + 2 + 1 hr))\n"; timeStr3 += 31; cout << "22: " << timeStr3 << " (same, 15:07:00)\n"; timeStr3 -= 7 * 60 + 15 * 3600; cout << "23: " << timeStr3 << " (same, 03:00:00)\n"; timeStruct.tm_sec = 30; timeStruct.tm_min = 30; timeStruct.tm_hour = 4; timeStruct.tm_mday = 1; timeStruct.tm_mon = 1; timeStruct.tm_year = 0; timeStr3 += timeStruct; cout << "24: " << timeStr3 << " (added 1 month, 1 day, 4:30:30)\n"; timeStr3 -= timeStruct; cout << "25: " << timeStr3 << " (subtracted that again)\n"; timeStruct = *timeStr3.timeStruct(); --timeStruct.tm_mday; timeStruct.tm_year -= (1970 - 1900); timeStr3 -= timeStruct; cout << "26: " << timeStr3 << " (begin of the epoch)\n"; DateTime dst(DateTime::LOCALTIME); dst.setMonth(DateTime::AUGUST); cout << "27: " << dst << ", DST: " << dst.dst() << " (LT in aug., show dst)\n"; cout << "28: " << dst.rfc2822() << " (same, rfc 2822)\n"; cout << "29: " << dst.rfc3339() << " (same, rfc 3339)\n"; dst.setMonth(DateTime::JANUARY); cout << "30: " << dst << ", DST: " << dst.dst() << " (LT in jan., show dst)\n"; cout << "31: " << dst.rfc2822() << " (same, rfc 2822)\n"; cout << "32: " << dst.rfc3339() << " (same, rfc 3339)\n"; DateTime utcDst(dst.utc()); cout << "33: " << dst.timeZoneShift(3 * 60) << " (UTC + 3 time zones)\n"; cout << "34: " << dst << " (time in jan. again)\n"; cout << "35: " << utcDst << " (same, UTC)\n"; cout << "36: " << utcDst.localTime() << " (same, LT)\n"; cout << "37: " << utcDst.timeZoneShift(3 * 60) << " (UTC + 3 time zones)\n"; istringstream ins("Tue Nov 18 15:06:29 2008"); ins >> dst; cout << "\n" "Extracting `" << ins.str() << "'\n"; cout << "38: " << dst << " (extracted)\n"; cout << "39: " << dst.utc() << " (same, UTC)\n"; ins.str("Fri Jul 18 15:06:29 2008"); ins >> dst; cout << "\n" "Extracting `" << ins.str() << "'\n"; cout << "40: " << dst << " (extracted)\n"; cout << "41: " << dst.utc() << " (same, UTC)\n"; } bobcat-3.19.01/datetime/driver/demos/0000755000175000017500000000000012222576533016310 5ustar frankfrankbobcat-3.19.01/datetime/driver/demos/asctime.cc0000644000175000017500000000027112222576533020244 0ustar frankfrank #include #include using namespace std; int main() { time_t utc = time(0); cout << asctime(gmtime(&utc)); return 0; } bobcat-3.19.01/datetime/driver/demos/localtime.cc0000644000175000017500000000043712222576533020574 0ustar frankfrank #include #include using namespace std; int main() { time_t utc = time(0); struct tm *ts; time_t local = mktime(ts = gmtime(&utc)); cout << ts->tm_hour << ' ' << utc - local << endl; return 0; } bobcat-3.19.01/datetime/driver/demos/utc.cc0000644000175000017500000000044212222576533017412 0ustar frankfrank #include #include using namespace std; int main() { time_t utc = time(0); struct tm *ts; time_t local = mktime(ts = localtime(&utc)); cout << ts->tm_hour << ' ' << utc - local << endl; return 0; } bobcat-3.19.01/datetime/driver/demos/erabody.cc0000644000175000017500000000064612222576533020252 0ustar frankfranktime_t seconds = time(0); tm timeStruct = *gmtime(&seconds); DateTime tmp(timeStruct); cout << tmp << endl; --timeStruct.tm_mday; // days start at 1: subtract 1 less than // the current day number to get '01' timeStruct.tm_year -= (1970 - 1900); // era starts at 1970, tm_year // is relative to 1900. tmp -= timeStruct; cout << tmp << endl; bobcat-3.19.01/datetime/driver/demos/inverses.cc0000644000175000017500000000317212222576533020460 0ustar frankfrank #include #include using namespace std; int main() { time_t utcSeconds = time(0); // UTC time struct tm ts; gmtime_r(&utcSeconds, &ts); // fill the ts struct cout << ts.tm_hour << " " << asctime(&ts); // display it // this number of seconds is returned // when computing secs from struct tm time_t retrievedUtcSeconds = mktime(&ts); gmtime_r(&retrievedUtcSeconds, &ts); // refill the struct tm cout << asctime(&ts); int correction = utcSeconds - retrievedUtcSeconds; cout << correction << endl; // retrieve seconds time_t correctedUtcSeconds = retrievedUtcSeconds + correction; gmtime_r(&correctedUtcSeconds, &ts); cout << asctime(&ts); cout << utcSeconds - mktime(localtime_r(&utcSeconds, &ts)) << endl; return 0; } /* Compute the correction for the current time zone It can also be computed as mktime(locatime()) - mktime(gmtime()) To compute the (UTC) number of seconds from a struct tm representing the time in UTC compute mktime(gmtime(tm)) + correction or compute mktime(localtime(tm)) To compute a struct tm for a certain display zone, add the zone to utc info and display according to the broken down time using gmtime(). To compute the matching utc time: compute mktime(localtime(tm)) - zoneshift Assuming a local time in a certain zone shift is available in a struct tm compute mktime(localtime(tm) - zoneshift to obtain the utc time */ bobcat-3.19.01/datetime/driver/demos/era.cc0000644000175000017500000000031412222576533017364 0ustar frankfrank #include #include #include using namespace std; using namespace FBB; int main() { #include "erabody.cc" return 0; } bobcat-3.19.01/datetime/weekday.f0000644000175000017500000000014612223023055015472 0ustar frankfrankinline DateTime::Weekday DateTime::weekday() const { return static_cast(d_tm.tm_wday); } bobcat-3.19.01/datetime/rfc3339.cc0000644000175000017500000000102512222576533015307 0ustar frankfrank#include "datetime.ih" string DateTime::rfc3339() const { ostringstream out; out << setfill('0') << 1900 + d_tm.tm_year << '-' << setw(2) << (d_tm.tm_mon + 1) << '-' << setw(2) << d_tm.tm_mday << ' '; timeStr(out) << ' ' << showpos << setw(3) << internal << d_displayZoneShift / 3600 << ':' << noshowpos << setw(2) << abs(d_displayZoneShift) % 3600 / 60; return out.str(); } bobcat-3.19.01/datetime/data.cc0000644000175000017500000000046512222576533015133 0ustar frankfrank#include "datetime.ih" char const *DateTime::s_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; char const *DateTime::s_day[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; bobcat-3.19.01/datetime/datetime7.cc0000644000175000017500000000043312222576533016100 0ustar frankfrank#include "datetime.ih" DateTime::DateTime(string const &timeStr, TimeType type) : d_type(type), d_displayZoneShift(0), d_dstShift(0) { istringstream in(timeStr); parse(in); // determine timestruct representing hour in UTC d_tm2timeType(); } bobcat-3.19.01/datetime/timezoneshift.f0000644000175000017500000000017112223023055016727 0ustar frankfrankinline DateTime DateTime::timeZoneShift(int displayZoneShift) const { return DateTime(d_utcSec, displayZoneShift); } bobcat-3.19.01/datetime/setyear.cc0000644000175000017500000000022412222576533015667 0ustar frankfrank#include "datetime.ih" bool DateTime::setYear(size_t year) { TimeStruct ts = d_tm; ts.tm_year = year - 1900; return updateTime(ts); } bobcat-3.19.01/datetime/setweekday.cc0000644000175000017500000000107012222576533016360 0ustar frankfrank#include "datetime.ih" bool DateTime::setWeekday(Weekday weekday, Relative where) { TimeStruct ts = d_tm; int difference = static_cast(weekday) - ts.tm_wday; switch (where) { case NEXT: difference += 7; break; case LAST: difference -= 7; break; case THIS_WEEK: break; default: throw Exception(1) << "DateTime::setWeekday(): invalid Relative spec."; } ts.tm_mday += difference; return updateTime(ts); } bobcat-3.19.01/datetime/timestruct2utcsec.cc0000644000175000017500000000033112222576533017706 0ustar frankfrank#include "datetime.ih" time_t DateTime::timeStruct2utcSec(TimeStruct *ts) { time_t time = mktime(ts); if (time == -1) { d_ok = false; return 0; } d_ok = true; return time; } bobcat-3.19.01/datetime/minutes.f0000644000175000017500000000010412223023055015517 0ustar frankfrankinline size_t DateTime::minutes() const { return d_tm.tm_min; } bobcat-3.19.01/datetime/datetime2.cc0000644000175000017500000000042312222576533016072 0ustar frankfrank#include "datetime.ih" // UTC + displayZoneShift = LOCALTIME DateTime::DateTime(int displayZoneShift) : d_type(LOCALTIME), d_utcSec(::time(0)), d_dstShift(0) { setDisplayZone(zoneShiftSeconds(displayZoneShift)); utcSec2timeStruct(&d_tm, d_utcSec); } bobcat-3.19.01/datetime/opeq.f0000644000175000017500000000016712223023055015010 0ustar frankfrankinline bool operator==(DateTime const &left, DateTime const &right) { return left.d_utcSec == right.d_utcSec; } bobcat-3.19.01/datetime/monthdaynr.f0000644000175000017500000000011012223023055016213 0ustar frankfrankinline size_t DateTime::monthDayNr() const { return d_tm.tm_mday; } bobcat-3.19.01/datetime/opneq.f0000644000175000017500000000016712223023055015166 0ustar frankfrankinline bool operator!=(DateTime const &left, DateTime const &right) { return left.d_utcSec != right.d_utcSec; } bobcat-3.19.01/datetime/to.cc0000644000175000017500000000054112222576533014637 0ustar frankfrank#include "datetime.ih" DateTime DateTime::to(TimeType type) const { if (type == UTC) return DateTime(d_utcSec, UTC); if (d_displayZoneShift) return DateTime(d_utcSec + d_displayZoneShift, LOCALTIME); bool ok; return DateTime(d_utcSec + defaultDisplayZoneShift() + dstCorrection(&ok), LOCALTIME); } bobcat-3.19.01/datetime/setminutes.cc0000644000175000017500000000022312222576533016412 0ustar frankfrank#include "datetime.ih" bool DateTime::setMinutes(int minutes) { TimeStruct ts = d_tm; ts.tm_min = minutes; return updateTime(ts); } bobcat-3.19.01/datetime/seconds.f0000644000175000017500000000010412223023055015471 0ustar frankfrankinline size_t DateTime::seconds() const { return d_tm.tm_sec; } bobcat-3.19.01/datetime/operatorplusis2.cc0000644000175000017500000000053612222576533017376 0ustar frankfrank#include "datetime.ih" DateTime &DateTime::operator+=(TimeStruct const &fields) { TimeStruct ts = d_tm; ts.tm_sec += fields.tm_sec; ts.tm_min += fields.tm_min; ts.tm_hour += fields.tm_hour; ts.tm_mday += fields.tm_mday; ts.tm_mon += fields.tm_mon; ts.tm_year += fields.tm_year; updateTime(ts); return *this; } bobcat-3.19.01/datetime/parse.cc0000644000175000017500000000124512222576533015331 0ustar frankfrank#include "datetime.ih" void DateTime::parse(istream &in) { in >> d_tm.tm_year; if (!in) parseFromDayName(in); // expect Sun (etc) else { // expect 2008-11-02 13:29:11+01:00 char sep; in >> sep >> d_tm.tm_mon; --d_tm.tm_mon; in >> sep >> d_tm.tm_mday >> d_tm.tm_hour >> sep >> d_tm.tm_min >> sep >> d_tm.tm_sec; in.ignore(6); // +01:00 } d_ok = in; d_errno = 0; if (d_ok) { d_tm.tm_year -= 1900; d_utcSec = timeStruct2utcSec(&d_tm); } } bobcat-3.19.01/datetime/weeknr.cc0000644000175000017500000000041312222576533015506 0ustar frankfrank#include "datetime.ih" size_t DateTime::weekNr() const { TimeStruct tmStruct; tmStruct.tm_mon = 0; tmStruct.tm_mday = 1; DateTime jan1(*this); jan1.setFields(tmStruct, MONTH | MONTHDAY); return 1 + (jan1.d_tm.tm_wday + d_tm.tm_yday) / 7; } bobcat-3.19.01/datetime/opadd2.f0000644000175000017500000000022712223023055015212 0ustar frankfrankinline DateTime operator+(DateTime const &left, // d_type tm const &right) { return DateTime(left) += right; } bobcat-3.19.01/datetime/opgreater.f0000644000175000017500000000016512223023055016032 0ustar frankfrankinline bool operator>(DateTime const &left, DateTime const &right) { return left.d_utcSec > right.d_utcSec; } bobcat-3.19.01/datetime/month.f0000644000175000017500000000013712223023055015166 0ustar frankfrankinline DateTime::Month DateTime::month() const { return static_cast(d_tm.tm_mon); } bobcat-3.19.01/datetime/opadd1.f0000644000175000017500000000022412223023055015206 0ustar frankfrankinline DateTime operator+(DateTime const &left, // d_type time_t right) { return DateTime(left) += right; } bobcat-3.19.01/datetime/opsubis1.f0000644000175000017500000000013312223023055015602 0ustar frankfrankinline DateTime &DateTime::operator-=(time_t seconds) { return operator+=(-seconds); } bobcat-3.19.01/datetime/yeardaynr.f0000644000175000017500000000011312223023055016031 0ustar frankfrankinline size_t DateTime::yearDayNr() const { return d_tm.tm_yday + 1; } bobcat-3.19.01/datetime/datetime1.cc0000644000175000017500000000056312222576533016076 0ustar frankfrank#include "datetime.ih" // Determine current UTC or LOCALTIME DateTime::DateTime(TimeType type) : d_type(type), d_utcSec(::time(0)) { setDisplayZone(defaultDisplayZoneShift() + dstCorrection()); // displayZoneCorrection for // `type' utcSec2timeStruct(&d_tm, d_utcSec); } bobcat-3.19.01/datetime/opleq.f0000644000175000017500000000016712223023055015164 0ustar frankfrankinline bool operator<=(DateTime const &left, DateTime const &right) { return left.d_utcSec <= right.d_utcSec; } bobcat-3.19.01/datetime/defaultdisplayzoneshift.cc0000644000175000017500000000023412222576533021160 0ustar frankfrank#include "datetime.ih" time_t DateTime::defaultDisplayZoneShift() const { TimeStruct ts; return d_utcSec - mktime(gmtime_r(&d_utcSec, &ts)); } bobcat-3.19.01/datetime/setmonth.cc0000644000175000017500000000136012222576533016056 0ustar frankfrank#include "datetime.ih" #include using namespace std; bool DateTime::setMonth(Month month, Relative where) { TimeStruct ts = d_tm; switch (where) { case NEXT: // For NEXT: At Sep, specify May: next year if (static_cast(month) < d_tm.tm_mon) ++ts.tm_year; break; case LAST: // For LAST: At Sep, specify Oct: previous year if (static_cast(month) > d_tm.tm_mon) --ts.tm_year; break; case THIS_YEAR: break; default: throw Exception(1) << "DateTime::setMonth(): invalid Relative spec."; } ts.tm_mon = month; return updateTime(ts); } bobcat-3.19.01/datetime/datetime8dep.cc0000644000175000017500000000132212222576533016570 0ustar frankfrank#include "datetime.ih" DateTime::DateTime(string const &timeStr, int displayZoneShift, int) : d_type(LOCALTIME) { static bool warned = false; if (!warned) { warned = true; cerr << "\n" "Warning: DateTime(string const &timeStr, " "int displayZoneShift, int utcZoneShift)\n" " This constructor is deprecated and is replaced by:\n" " DateTime(string const &timeStr, " "int displayZoneShift)\n"; } istringstream in(timeStr); parse(in); // determine timestruct representing hour in UTC d_tm2d_tm(displayZoneShift); } bobcat-3.19.01/datetime/opsub1.f0000644000175000017500000000022412223023055015247 0ustar frankfrankinline DateTime operator-(DateTime const &left, // d_type time_t right) { return DateTime(left) -= right; } bobcat-3.19.01/datetime/year.f0000644000175000017500000000011112223023055014771 0ustar frankfrankinline size_t DateTime::year() const { return d_tm.tm_year + 1900; } bobcat-3.19.01/datetime/setseconds.cc0000644000175000017500000000022212222576533016363 0ustar frankfrank#include "datetime.ih" bool DateTime::setSeconds(int seconds) { TimeStruct ts = d_tm; ts.tm_sec = seconds; return updateTime(ts); } bobcat-3.19.01/datetime/yearday.f0000644000175000017500000000010512223023055015472 0ustar frankfrankinline size_t DateTime::yearDay() const { return d_tm.tm_yday; } bobcat-3.19.01/datetime/datetime.ih0000644000175000017500000000041112223023055016003 0ustar frankfrank#include "datetime" #include #include #include #include #include #include #include using namespace std; using namespace FBB; #include "zoneshiftseconds.f" #include "timestruct.f" bobcat-3.19.01/datetime/dtm2timetype.cc0000644000175000017500000000020012222576533016634 0ustar frankfrank#include "datetime.ih" void DateTime::d_tm2timeType() { d_tm.tm_isdst = 0; d_tm2utcSec(); displayShift2d_tm(); } bobcat-3.19.01/decryptbuf/0000755000175000017500000000000012257325714014262 5ustar frankfrankbobcat-3.19.01/decryptbuf/lastok.f0000644000175000017500000000007512223023055015712 0ustar frankfrankinline bool DecryptBuf::lastOK() { return s_completed; } bobcat-3.19.01/decryptbuf/done.cc0000644000175000017500000000061612222576534015521 0ustar frankfrank#include "decryptbuf.ih" void DecryptBuf::done() { update(); int outLen; if ( !EVP_DecryptFinal_ex(&d_pimpl->ctx, reinterpret_cast(d_pimpl->out), &outLen) ) throw Exception() << "Padding incorrect"; d_pimpl->outStream.write(d_pimpl->out, outLen); d_pimpl->active = false; } bobcat-3.19.01/decryptbuf/destructor.cc0000644000175000017500000000033512222576534016770 0ustar frankfrank#include "decryptbuf.ih" DecryptBuf::~DecryptBuf() { if (d_pimpl->active) try { done(); s_completed = true; } catch(...) { s_completed = false; } delete d_pimpl; } bobcat-3.19.01/decryptbuf/destructor.f0000644000175000017500000000012412223023055016606 0ustar frankfrankinline DecryptBufImp::~DecryptBufImp() { delete [] buffer; delete [] out; } bobcat-3.19.01/decryptbuf/decryptbuf.ih0000644000175000017500000000105412223023055016735 0ustar frankfrank#include "decryptbuf" #include #include #include namespace FBB { struct DecryptBufImp { EVP_CIPHER_CTX ctx; EVP_CIPHER const *md; bool active; size_t bufsize; char *buffer; char *out; std::ostream &outStream; DecryptBufImp(std::ostream &outStream, size_t bufsize); ~DecryptBufImp(); // destructor.i }; #include "destructor.f" } // FBB using namespace std; using namespace FBB; bobcat-3.19.01/decryptbuf/open.cc0000644000175000017500000000016612222576534015535 0ustar frankfrank#include "decryptbuf.ih" void DecryptBuf::open() { setp(d_pimpl->buffer, d_pimpl->buffer + d_pimpl->bufsize); } bobcat-3.19.01/decryptbuf/setiv.cc0000644000175000017500000000076512222576534015733 0ustar frankfrank#include "decryptbuf.ih" void DecryptBuf::setIv(string iv) { if (d_pimpl->active) throw Exception(1) << "Can't change IV during encryption"; if (iv.empty()) throw Exception(1) << "Decryptbuf::setIV: initialization vector cannot be empty"; iv.resize(EVP_MAX_IV_LENGTH); if ( !EVP_EncryptInit_ex(&d_pimpl->ctx, 0, 0, 0, reinterpret_cast(iv.data())) ) throw Exception(1) << "Couldn't set IV"; } bobcat-3.19.01/decryptbuf/setrounds.cc0000644000175000017500000000033612222576534016621 0ustar frankfrank#include "decryptbuf.ih" bool DecryptBuf::setRounds(size_t nRounds) { return EVP_CIPHER_CTX_ctrl(&d_pimpl->ctx, EVP_CTRL_SET_RC5_ROUNDS, nRounds, 0); } bobcat-3.19.01/decryptbuf/driver/0000755000175000017500000000000012224221270015537 5ustar frankfrankbobcat-3.19.01/decryptbuf/driver/build0000755000175000017500000000057712222576534016613 0ustar frankfrank#!/bin/sh # ln -s .. bobcat # # g++ -I. --std=c++0x -O2 -Wall -o driver driver.cc -lssl -lbobcat \ # -L../tmp -ldecryptbuf # # rm bobcat # echo g++ --std=c++0x -O2 -Wall -o driver driver.cc -lbobcat # g++ --std=c++0x -O2 -Wall -o driver driver.cc -lbobcat tput clear LIBS=" -lbobcat" GPP="g++ --std=c++0x" CMD="$GPP -o driver -Wall *.cc ${LIBS} -s" echo ${CMD} ${CMD} bobcat-3.19.01/decryptbuf/driver/driver.cc0000644000175000017500000000124012222576534017354 0ustar frankfrank#include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) throw Errno("1st arg: method, 2nd arg: key, 3rd arg: file to " "decrypt (to stdout), 4th arg: iv"); cerr << "Key: `" << argv[2] << "'\n" "IV: `" << argv[4] << "'\n"; DecryptBuf decryptbuf(cout, argv[1], argv[2], argv[4]); ostream out(&decryptbuf); ifstream in(argv[3]); out << in.rdbuf(); // decryptbuf.done(); // optionally } catch(Errno const &err) { cout << err.why() << endl; return 1; } bobcat-3.19.01/decryptbuf/data.cc0000644000175000017500000000007012222576534015477 0ustar frankfrank#include "decryptbuf.ih" bool DecryptBuf::s_completed; bobcat-3.19.01/decryptbuf/cipherctx.cc0000644000175000017500000000014012222576534016555 0ustar frankfrank#include "decryptbuf.ih" EVP_CIPHER_CTX *DecryptBuf::cipherCtx() { return &d_pimpl->ctx; } bobcat-3.19.01/decryptbuf/decryptbuf0000644000175000017500000000165712223023055016347 0ustar frankfrank#ifndef INCLUDED_DECRYPTBUF_ #define INCLUDED_DECRYPTBUF_ #include #include #include namespace FBB { struct DecryptBufImp; class DecryptBuf: public std::streambuf { DecryptBufImp *d_pimpl; static bool s_completed; public: DecryptBuf(std::ostream &outStream, char const *type, std::string key, std::string iv, size_t bufsize = 1024); virtual ~DecryptBuf(); void setIv(std::string iv); bool setRounds(size_t nRounds); // RC5 8, 12 or 16 void done(); static bool lastOK(); // .f protected: EVP_CIPHER_CTX *cipherCtx(); private: void update(); void open(); void installKey(std::string const &key, size_t length); virtual int overflow(int c); }; #include "lastok.f" } // FBB #endif bobcat-3.19.01/decryptbuf/decryptbuf1.cc0000644000175000017500000000247712222576534017033 0ustar frankfrank#include "decryptbuf.ih" DecryptBuf::DecryptBuf(ostream &outStream, char const *type, string key, string iv, size_t bufsize) : d_pimpl(new DecryptBufImp(outStream, bufsize)) { try { OpenSSL_add_all_ciphers(); d_pimpl->md = EVP_get_cipherbyname(type); if (!d_pimpl->md) { if (type == 0) type = "** unspecified cipher type **"; throw Exception(1) << "DecryptBuf `" << type << "' not available"; } size_t keyLength = key.length(); if (keyLength > EVP_MAX_KEY_LENGTH) keyLength = EVP_MAX_KEY_LENGTH; key.resize(EVP_MAX_KEY_LENGTH); iv.resize(EVP_MAX_IV_LENGTH); EVP_CIPHER_CTX_init(&d_pimpl->ctx); if ( !EVP_DecryptInit_ex(&d_pimpl->ctx, d_pimpl->md, 0, 0, // no key yet, is entered next reinterpret_cast(iv.data())) ) throw Exception(1) << "DecryptBuf: initialization failed"; installKey(key, keyLength); d_pimpl->buffer = new char[bufsize]; d_pimpl->out = new char[ bufsize + EVP_CIPHER_CTX_block_size(&d_pimpl->ctx)]; open(); } catch (...) { delete d_pimpl; throw; } } bobcat-3.19.01/decryptbuf/overflow.cc0000644000175000017500000000031012222576534016426 0ustar frankfrank#include "decryptbuf.ih" int DecryptBuf::overflow(int c) { update(); open(); if (c != EOF) { *pptr() = static_cast(c); pbump(1); } return c; } bobcat-3.19.01/decryptbuf/installkey.cc0000644000175000017500000000054012222576534016747 0ustar frankfrank#include "decryptbuf.ih" void DecryptBuf::installKey(string const &key, size_t numberOfBytes) { EVP_CIPHER_CTX_set_key_length(&d_pimpl->ctx, numberOfBytes); if ( !EVP_EncryptInit_ex(&d_pimpl->ctx, 0, 0, reinterpret_cast(key.data()), 0) ) throw Exception(1) << "Couldn't set Key"; } bobcat-3.19.01/decryptbuf/update.cc0000644000175000017500000000057412222576534016061 0ustar frankfrank#include "decryptbuf.ih" void DecryptBuf::update() { d_pimpl->active = true; int outLen; EVP_DecryptUpdate(&d_pimpl->ctx, reinterpret_cast(d_pimpl->out), &outLen, reinterpret_cast(d_pimpl->buffer), pptr() - pbase()); d_pimpl->outStream.write(d_pimpl->out, outLen); } bobcat-3.19.01/decryptbuf/decryptbufimp.cc0000644000175000017500000000027512222576534017452 0ustar frankfrank#include "decryptbuf.ih" DecryptBufImp::DecryptBufImp(ostream &outStream, size_t bufsize) : active(false), bufsize(bufsize), buffer(0), out(0), outStream(outStream) {} bobcat-3.19.01/diffiehellman/0000755000175000017500000000000012257325714014702 5ustar frankfrankbobcat-3.19.01/diffiehellman/callback.cc0000644000175000017500000000031512222576536016746 0ustar frankfrank#include "diffiehellman.ih" namespace { char info[] = {0, '.', '-', '+'}; } void DiffieHellman::callback(int indicator, int, void *) { if (indicator) cout.put(info[indicator]).flush(); } bobcat-3.19.01/diffiehellman/diffiehellman.ih0000644000175000017500000000036512222576536020021 0ustar frankfrank#include "diffiehellman" #include #include #include #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/diffiehellman/key2.cc0000644000175000017500000000026512222576536016070 0ustar frankfrank#include "diffiehellman.ih" string DiffieHellman::key(std::string const &peerPublicFileName) { ifstream in; Exception::open(in, peerPublicFileName); return key(in); } bobcat-3.19.01/diffiehellman/diffiehellman5.cc0000644000175000017500000000042212222576536020065 0ustar frankfrank#include "diffiehellman.ih" DiffieHellman::DiffieHellman(istream &publicStream, istream &privateStream) : DiffieHellman(publicStream) { if (not read(privateStream, &d_dh->priv_key)) throw Exception() << s_header << "could not load private key"; } bobcat-3.19.01/diffiehellman/write.cc0000644000175000017500000000061512222576536016347 0ustar frankfrank#include "diffiehellman.ih" void DiffieHellman::write(ostream &out, BIGNUM const *bn, char *buffer, uint32_t nBytes) const { uint32_t nBytesStd = htonl(nBytes); out.write(reinterpret_cast(&nBytesStd), sizeof(uint32_t)); BN_bn2bin(bn, reinterpret_cast(buffer)); out.write(buffer, nBytes); } bobcat-3.19.01/diffiehellman/skip.cc0000644000175000017500000000043712222576536016165 0ustar frankfrank#include "diffiehellman.ih" void DiffieHellman::skip(istream &in, size_t count) { for (; count--; ) { uint32_t length; in.read(reinterpret_cast(&length), sizeof(uint32_t)); length = ntohl(length); in.seekg(length, ios::cur); } } bobcat-3.19.01/diffiehellman/key1.cc0000644000175000017500000000177312222576536016074 0ustar frankfrank#include "diffiehellman.ih" string DiffieHellman::key() const { size_t length = DH_size(d_dh.get()); char buffer[length]; if ( DH_compute_key(reinterpret_cast(buffer), d_otherPubKey.get(), d_dh.get()) == -1 ) throw Exception() << s_header << "could not compute the shared key"; string ret(buffer, buffer + length); BigInt theKey(ret); BigInt prime(const_cast(d_dh->p)); BigInt qValue((prime - 1) >> 1); // (prime - 1) / 2 is also prime, as // prima is a safe prime. qValue, according to // RFC 2631 should be so that p = j * q + 1 // is prime. Here j == 2 if ( theKey == 1 || theKey >= prime - 1 || theKey.expModc(qValue, prime) != 1 ) throw Exception() << "Key not resistant to the small group attack"; return ret; } bobcat-3.19.01/diffiehellman/driver/0000755000175000017500000000000012224221317016161 5ustar frankfrankbobcat-3.19.01/diffiehellman/driver/build0000755000175000017500000000022212222576536017220 0ustar frankfrank#!/bin/bash # For development purposes: g++ --std=c++0x -O2 -Wall -o driver -isystem ../../tmp driver.cc \ -L ../../tmp/lib/ -lbobcat -lssl bobcat-3.19.01/diffiehellman/driver/driver.cc0000644000175000017500000000163512222576536020006 0ustar frankfrank #include #include #include using namespace FBB; using namespace std; int main(int argc, char **argv) try { if (argc == 1) { DiffieHellman dh(1024, 5, true); dh.save("init", DiffieHellman::SAVE_SECRET_KEY); } if (argc == 2) { DiffieHellman dh("init.pub"); dh.save("peer", DiffieHellman::SAVE_SECRET_KEY); string key = dh.key(); cout << "Key length: " << key.length() << '\n'; ofstream outkey("peerkey"); outkey.write(key.data(), key.length()); } if (argc == 3) { DiffieHellman dh("init.pub", "init.sec"); string key = dh.key("peer.pub"); cout << "Key length: " << key.length() << '\n'; ofstream outkey("initkey"); outkey.write(key.data(), key.length()); } } catch (std::exception const &exc) { std::cout << exc.what() << '\n'; } bobcat-3.19.01/diffiehellman/data.cc0000644000175000017500000000012612222576536016123 0ustar frankfrank#include "diffiehellman.ih" char const *DiffieHellman::s_header = "DiffieHellman: "; bobcat-3.19.01/diffiehellman/diffiehellman2.cc0000644000175000017500000000027712222576536020072 0ustar frankfrank#include "diffiehellman.ih" DiffieHellman::DiffieHellman(string const &initiatorPublicFileName) : DiffieHellman(*unique_ptr(new ifstream(initiatorPublicFileName))) {} bobcat-3.19.01/diffiehellman/diffiehellman3.cc0000644000175000017500000000056112222576536020067 0ustar frankfrank#include "diffiehellman.ih" DiffieHellman::DiffieHellman(istream &initiatorPublicStream) : d_dh(DH_new(), DH_free), d_otherPubKey(0, BN_free) { if (not load(initiatorPublicStream)) throw Exception() << s_header << "could not load public values"; checkDHparameters(); d_otherPubKey.reset(d_dh->pub_key); d_dh->pub_key = 0; } bobcat-3.19.01/diffiehellman/checkdhparameters.cc0000644000175000017500000000147212222576536020674 0ustar frankfrank#include "diffiehellman.ih" void DiffieHellman::checkDHparameters() { int result; if (DH_check(d_dh.get(), &result) == 0) result = CHECK_FAILS; if (result == 0) return; if (result & (DH_CHECK_P_NOT_PRIME | DH_CHECK_P_NOT_SAFE_PRIME)) throw Exception() << s_header << "invalid prime generated"; BigInt generator(const_cast(d_dh->g)); if (result & DH_NOT_SUITABLE_GENERATOR) wmsg << s_header << generator << " is not a generator for the " "computed prime" << endl; else if (result & DH_UNABLE_TO_CHECK_GENERATOR) wmsg << s_header << "cannot check the validity of generator " << generator << endl; else if (result & CHECK_FAILS) throw Exception() << s_header << "parameter check fails"; } bobcat-3.19.01/diffiehellman/diffiehellman1.cc0000644000175000017500000000075112222576536020066 0ustar frankfrank#include "diffiehellman.ih" DiffieHellman::DiffieHellman(size_t primeLength, size_t generator, bool progress) : d_dh( DH_generate_parameters( primeLength, generator, progress? callback : 0, 0 ), DH_free ), d_otherPubKey(0, DH_free) { if (progress) cout << endl; if (d_dh == 0) throw Exception() << s_header << "generating parameters failed"; checkDHparameters(); } bobcat-3.19.01/diffiehellman/key3.cc0000644000175000017500000000057712222576536016077 0ustar frankfrank#include "diffiehellman.ih" string DiffieHellman::key(istream &peerPublicStream) { skip(peerPublicStream, 2); BIGNUM *otherPubKey; if (not read(peerPublicStream, &otherPubKey)) throw Exception() << s_header << "could not read the peer's public key"; d_otherPubKey.reset(otherPubKey); return key(); } bobcat-3.19.01/diffiehellman/read.cc0000644000175000017500000000063612222576536016133 0ustar frankfrank#include "diffiehellman.ih" bool DiffieHellman::read(istream &in, BIGNUM **dest) { uint32_t length; in.read(reinterpret_cast(&length), sizeof(uint32_t)); length = ntohl(length); char buffer[length]; in.read(buffer, length); BN_free(*dest); *dest = BN_bin2bn( reinterpret_cast(buffer), length, 0 ); return *dest; } bobcat-3.19.01/diffiehellman/diffiehellman4.cc0000644000175000017500000000045512222576536020072 0ustar frankfrank#include "diffiehellman.ih" DiffieHellman::DiffieHellman(string const &publicFileName, string const &privateFileName) : DiffieHellman(*unique_ptr(new ifstream(publicFileName)), *unique_ptr(new ifstream(privateFileName))) {} bobcat-3.19.01/diffiehellman/save.cc0000644000175000017500000000233112222576536016150 0ustar frankfrank#include "diffiehellman.ih" void DiffieHellman::save(string const &basename, SecretKey action) const { if (DH_generate_key(d_dh.get()) == 0) throw Exception() << "DiffieHellman::save: could not generate " "public/private keys"; int nBytes[] = { BN_num_bytes(d_dh->p), BN_num_bytes(d_dh->g), BN_num_bytes(d_dh->pub_key), BN_num_bytes(d_dh->priv_key) }; unique_ptr dest(new char[*max_element(nBytes, nBytes + 4)]); ofstream out; Exception::open(out, basename + ".pub"); write(out, d_dh->p, dest.get(), nBytes[0]); write(out, d_dh->g, dest.get(), nBytes[1]); write(out, d_dh->pub_key, dest.get(), nBytes[2]); if (not out) throw Exception() << "Could not write public DH info to `" << basename + ".pub'"; if (action == DONT_SAVE_SECRET_KEY) return; out.close(); Exception::open(out, basename + ".sec"); write(out, d_dh->priv_key, dest.get(), nBytes[3]); if (not out) throw Exception() << "Could not write private DH info to `" << basename + ".sec'"; } bobcat-3.19.01/diffiehellman/diffiehellman0000644000175000017500000000752312222576537017426 0ustar frankfrank#ifndef INCLUDED_BOBCAT_DIFFIEHELLMAN_ #define INCLUDED_BOBCAT_DIFFIEHELLMAN_ #include #include #include #include namespace FBB { class DiffieHellman { std::shared_ptr d_dh; std::shared_ptr d_otherPubKey; // public key of the other party static char const *s_header; public: enum SecretKey { DONT_SAVE_SECRET_KEY, SAVE_SECRET_KEY }; enum { CHECK_FAILS = ~(DH_CHECK_P_NOT_PRIME | DH_CHECK_P_NOT_SAFE_PRIME | DH_NOT_SUITABLE_GENERATOR | DH_UNABLE_TO_CHECK_GENERATOR) }; // The initiator calls this constructor, which computes the common // DH parameters DiffieHellman(size_t primeLength = 1024, size_t generator = 5, bool progress = false); // The initiator saves the public info on basename.pub // and, by providing 'SAVE_SECRET_KEY, the secret info on // basename.sec void save(std::string const &basename, SecretKey action = DONT_SAVE_SECRET_KEY) const; // The initiator sends basename.pub to the peer, who reads // basename.pub using this constructor: DiffieHellman(std::string const &initiatorPublicFileName); // Alternatively, use this constructor expecting an istream: DiffieHellman(std::istream &initiatorPublicStream); // The peer now saves *his/her* public and (optionally) private // info: by calling save, providing a basename and optionally a // SecretKey argument. Next, the peer sends his/her public info // to the initiator. // The peer can already now determine the symmetric encryption // key, since he/she has // - The DH prime and generator; // - The initiator's public key; // - His/her own secret key. // The key is obtained by calling std::string key() const; // The initiator has two options: - After calling save and // transmitting the public data to the peer the DiffieHellman // object is kept, and the initiator waits for the peer's public // key to become available. In that case the initiator's private // key doesn't have to be saved, and ephemeral DH is // obtained. After receiving the peer's public parameters the // initiator calls either of these overloaded versions of key to // obtain the symmetric key: std::string key(std::string const &peerPublicFileName); std::string key(std::istream &peerPublicStream); // Otherwise the initiator creates another DiffieHellman object, // using the 4th or 5th constructor, and then calls either of the // last two key members to obtain the symmetric key. DiffieHellman(std::string const &initiatorPublicFileName, std::string const &initiatorPrivateFileName); // Alternatively, use this constructor expecting istreams: DiffieHellman(std::istream &initiatorPublicStream, std::istream &initiatorPrivateStream); private: void checkDHparameters(); bool load(std::istream &publicData); void write(std::ostream &out, BIGNUM const *bn, char *buffer, uint32_t nBytes) const; bool read(std::istream &in, BIGNUM **dest); static void skip(std::istream &in, size_t count); static void callback(int, int, void *); // std::string publicKey() const; // std::string sharedKey(BigInt const &peersPublicKey // private: // // DH *newDH(); }; } // FBB #endif bobcat-3.19.01/diffiehellman/load.cc0000644000175000017500000000032512222576537016133 0ustar frankfrank#include "diffiehellman.ih" bool DiffieHellman::load(istream &publicData) { return read(publicData, &d_dh->p) && read(publicData, &d_dh->g) && read(publicData, &d_dh->pub_key); } bobcat-3.19.01/digestbuf/0000755000175000017500000000000012257325714014067 5ustar frankfrankbobcat-3.19.01/digestbuf/destructor.cc0000644000175000017500000000011112222576524016564 0ustar frankfrank#include "digestbuf.ih" DigestBuf::~DigestBuf() { delete d_pimpl; } bobcat-3.19.01/digestbuf/operatorinsert.cc0000644000175000017500000000045412222576524017460 0ustar frankfrank#include "digestbuf.ih" namespace FBB { std::ostream &operator<<(std::ostream &out, DigestBuf const &digestbuf) { OHexStreambuf ohex(out); ostream outs(&ohex); outs.write(digestbuf.d_pimpl->digest.data(), digestbuf.d_pimpl->digest.length()); return out; } } // FBB bobcat-3.19.01/digestbuf/digestbuf0000644000175000017500000000127112222576524015766 0ustar frankfrank#ifndef INCLUDED_BOBCAT_DIGESTBUF_ #define INCLUDED_BOBCAT_DIGESTBUF_ #include #include namespace FBB { struct DigestBufImp; class DigestBuf: public std::streambuf { friend std::ostream &operator<<(std::ostream &out, DigestBuf const &digestbuf); DigestBufImp *d_pimpl; public: explicit DigestBuf(char const *type, size_t bufsize = 1024); virtual ~DigestBuf(); void open(); void close(); std::string const &hash() const; private: virtual int overflow(int c); }; std::ostream &operator<<(std::ostream &out, DigestBuf const &digestbuf); } // FBB #endif bobcat-3.19.01/digestbuf/digestbuf1.cc0000644000175000017500000000107312222576524016433 0ustar frankfrank#include "digestbuf.ih" DigestBuf::DigestBuf(char const *type, size_t bufsize) : d_pimpl(new DigestBufImp(bufsize)) { try { OpenSSL_add_all_digests(); d_pimpl->md = EVP_get_digestbyname(type); if (!d_pimpl->md) { if (type == 0) type = "** unspecified digest type **"; throw Exception(1) << "DigestBuf `" << type << "' not available"; } d_pimpl->buffer = new char[bufsize]; open(); } catch (...) { delete d_pimpl; throw; } } bobcat-3.19.01/digestbuf/digestbuf.ih0000644000175000017500000000100412223023055016342 0ustar frankfrank#include "digestbuf" #include #include #include #include #include #include "../ohexstreambuf/ohexstreambuf" namespace FBB { struct DigestBufImp { EVP_MD_CTX ctx; EVP_MD const *md; std::string digest; char *buffer; size_t bufsize; DigestBufImp(size_t bufsize); ~DigestBufImp(); // destructor.i }; #include "destructor.f" } // FBB using namespace std; using namespace FBB; bobcat-3.19.01/digestbuf/destructor.f0000644000175000017500000000007612223023055016421 0ustar frankfrankinline DigestBufImp::~DigestBufImp() { delete[] buffer; } bobcat-3.19.01/digestbuf/open.cc0000644000175000017500000000031612222576524015336 0ustar frankfrank#include "digestbuf.ih" void DigestBuf::open() { EVP_MD_CTX_init(&d_pimpl->ctx); EVP_DigestInit_ex(&d_pimpl->ctx, d_pimpl->md, 0); setp(d_pimpl->buffer, d_pimpl->buffer + d_pimpl->bufsize); } bobcat-3.19.01/digestbuf/digestbufimp.cc0000644000175000017500000000015512222576524017060 0ustar frankfrank#include "digestbuf.ih" DigestBufImp::DigestBufImp(size_t bufsize) : buffer(0), bufsize(bufsize) {} bobcat-3.19.01/digestbuf/hash.cc0000644000175000017500000000014012222576524015313 0ustar frankfrank#include "digestbuf.ih" string const &DigestBuf::hash() const { return d_pimpl->digest; } bobcat-3.19.01/digestbuf/driver/0000755000175000017500000000000012222576524015361 5ustar frankfrankbobcat-3.19.01/digestbuf/driver/build0000755000175000017500000000045212222576524016407 0ustar frankfrank#!/bin/sh # ln -s .. bobcat #g++ -I. --std=c++0x -O2 -Wall -o driver driver.cc -lssl -lbobcat \ # -L../../ohexstreambuf/tmp -L../tmp -ldigestbuf -lohexstreambuf # rm bobcat tput clear LIBS=" -lbobcat" GPP="g++ --std=c++0x" CMD="$GPP -o driver -Wall *.cc ${LIBS} -s" echo ${CMD} ${CMD} bobcat-3.19.01/digestbuf/driver/driver.cc0000644000175000017500000000105712222576524017166 0ustar frankfrank#include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { DigestBuf digestbuf(argv[1]); ostream out(&digestbuf); string hw("hello world\n"); out << hw; digestbuf.close(); cout << ">" << digestbuf << "<" << endl; digestbuf.open(); out.write(hw.c_str(), hw.length()); digestbuf.close(); cout << ">" << digestbuf << "<" << endl; } catch(Errno const &err) { cout << err.why() << endl; return 1; } bobcat-3.19.01/digestbuf/overflow.cc0000644000175000017500000000046312222576524016243 0ustar frankfrank#include "digestbuf.ih" int DigestBuf::overflow(int c) { EVP_DigestUpdate(&d_pimpl->ctx, d_pimpl->buffer, d_pimpl->bufsize); setp(d_pimpl->buffer, d_pimpl->buffer + d_pimpl->bufsize); if (c != EOF) { *pptr() = static_cast(c); pbump(1); } return c; } bobcat-3.19.01/digestbuf/close.cc0000644000175000017500000000077112222576524015507 0ustar frankfrank#include "digestbuf.ih" void DigestBuf::close() { char *digestbuf = new char[EVP_MAX_MD_SIZE]; if (pptr() > pbase()) EVP_DigestUpdate(&d_pimpl->ctx, d_pimpl->buffer, pptr() - pbase()); unsigned int digestbufLen; EVP_DigestFinal_ex(&d_pimpl->ctx, reinterpret_cast(digestbuf), &digestbufLen); d_pimpl->digest.assign(digestbuf, digestbufLen); delete[] digestbuf; EVP_MD_CTX_cleanup(&d_pimpl->ctx); } bobcat-3.19.01/documentation/0000755000175000017500000000000011714560544014763 5ustar frankfrankbobcat-3.19.01/documentation/man/0000755000175000017500000000000012257557715015547 5ustar frankfrankbobcat-3.19.01/documentation/man/bobcat.yo0000644000175000017500000007226512242121037017340 0ustar frankfrankincludefile(include/header) manpage(Bobcat)(7)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (C++ Classes) whenhtml(center(htmlcommand())) manpagename(Bobcat)(Overview of classes in the Bobcat library) manpagedescription() The classes of the bf(Bobcat) library may be used after including tt(bobcat/classname) in sources. Generally, programs using the bf(Bobcat) library must be at least linked against the bf(Bobcat) library. Refer to section bf(LINKING) for more informatin about linking programs to required libraries. All classes and other elements are defined in the tt(FBB) namespace. For some classes em(manipulators) are available, which are defined in the tt(FBB) namespace. An overview of all manipulators defined in the tt(FBB) namespace is provided by tt(man -e bobcat manipulators). Beyond this section the section bf(CATEGORIES) groups classes that somehow belong together in various categories. The following classes and template functions are available: bf(FBB::Align): Specifies tt(Table(Buf)) column and element alignments.nl() Manpage(align) bf(FBB::Arg): Interfaces the command line arguments, allowing for short- and long options. The class is implemented as a tt(Singleton).nl() Manpage(arg) bf(FBB::ArgConfig): Inherits from tt(Arg) and tt(ConfigFile) allowing for options to be specified as command line options and/or configuration file options. The class is implemented as a tt(Singleton).nl() Manpage(argconfig) bf(FBB::A2x): Ascii-to-x conversions of any type supporting extractions from tt(i[string]stream) objects. Manpage(a2x) bf(FBB::BigInt): Wrapper class around the openssl BN_ functions for unlimited integer precision arithmetic. nl() Manpage(bigint) bf(FBB::binary_search): A modification of the STL tt(binary_search) algorithm returning the location of the searched value in a sorted series of values. nl() Manpage(binarysearch) bf(FBB::BinOps): A series of function templates implementing binary operators for classes that implement the matching binary assignment operators themselves. nl() Manpage(binops) bf(FBB::CGI): a class implementing the facilities accessing the data made available through the Common Gateway Interface.nl() Manpage(cgi) bf(FBB::Cidr): a class testing whether IP4 Internet addresses belong to address ranges defined by Classless Inter-Domain Routing (CIDR) address block specifications.nl() Manpage(cidr) bf(FBB::ClientSocket): a socket for tcp-communication with a server.nl() Manpage(clientsocket) bf(FBB::CmdFinder): Command-function associations.nl() Manpage(cmdfinder) bf(FBB::CmdFinderBase): Base class for tt(CmdFinder).nl() Manpage(cmdfinderbase) bf(FBB::ConfigFile): Processing standard configuration files.nl() Manpage(configfile) bf(FBB::DateTime): Manipulations with date and time values.nl() Manpage(datetime) bf(FBB::DecryptBuf): Decrypting information.nl() Manpage(decryptbuf) bf(FBB::DiffieHellman): Computing shared keys using the Diffie-Hellman algorithm.nl() Manpage(diffiehellman) bf(FBB::DigestBuf): Computing message digests.nl() Manpage(digestbuf) bf(FBB::EncryptBuf): Encrypting information.nl() Manpage(encryptbuf) bf(FBB::Exception): objects of this class accept tt(ostream) insertions, and are also tt(std::exception) objects.nl() Manpage(exception) bf(FBB::Fork): Defines bf(fork)(2) as part of a Template Algorithm Design Pattern. nl() Manpage(fork) bf(FBB::GetHostent): Obtains tt(hostent) struct from hostname or -address. nl() Manpage(gethostent) bf(FBB::Glob): Obtain a list of files matching a certain pattern.nl() Manpage(glob) bf(FBB::HmacBuf): Computing HMAC message digests.nl() Manpage(hmacbuf) bf(FBB::Hostname): Derived from tt(Hostent), allows the initialization from a tt(std::string), or from an tt(FBB::InetAddrress). nl() Manpage(hostname) bf(FBB::IBase64Stream): stream implementing base64 encoding and decoding, using a tt(FBB::Base64Streambuf) stream buffer.nl() Manpage(ibase64stream) bf(FBB::IBase64Streambuf): tt(FBB::IFilterStreambuf) specialization implementing base64 encoding and decoding.nl() Manpage(ibase64streambuf) bf(FBB::IFdStream): stream extracting information from a device whose file descriptor is available. nl() Manpage(ifdstream) bf(FBB::IFdStreambuf): Input stream buffer initialized by a file descriptor.nl() Manpage(ifdstreambuf) bf(FBB::IFilterStreambuf): tt(std::streambuf) specialization implementing an tt(std::istream) filtering design pattern.nl() Manpage(ifilterstreambuf) bf(FBB::Indent): Class and manipulators performing text indentation. nl() Manpage(indent) bf(FBB::InetAddress): Base class (no public constructor) for objects representing an internet address as used with sockets. Contains address and portnumbers. nl() Manpage(inetaddress) bf(FBB::IOStream): class combining tt(std::istream) and tt(std::ostream) features. nl() Manpage(iostream) bf(FBB::IOStreambuf): tt(std::streambuf) specialization allowing combined input and output operations. nl() Manpage(iostreambuf) bf(FBB::ISharedStream): tt(std::istream) operations on shared memory.nl() Manpage(isharedstream) bf(FBB::IRandStream): stream to extract random numbers from. nl() Manpage(irandstream) bf(FBB::ISymCryptStream): stream implementing symmetric encryption and decryption, using a tt(FBB::ISymCryptStreambuf) stream buffer.nl() Manpage(isymcryptstream) bf(FBB::ISymCryptStreambuf): tt(FBB::IFilterStreambuf) specialization implementing symmetric cryptography.nl() Manpage(isymcryptstreambuf) bf(FBB::Hash...): Various template classes implementing mapping containers using hashing.nl() Manpage(hash) bf(FBB::Hostent): Wrapper around the tt(hostent) struct. nl() Manpage(hostent) bf(FBB::level): Manipulator setting the log-level of tt(FBB::Log) objects.nl() Manpage(level) bf(FBB::lm): Manipulator setting the left margin of tt(FBB::OFoldStream) objects.nl() Manpage(lm) bf(FBB::LocalClientSocket): a Unix domain socket for tcp-communication with a Unix domain (local) server.nl() Manpage(localclientsocket) bf(FBB::LocalServerSocket): defines a Unix domain socket to which clients on the local host can connect.nl() Manpage(localserversocket) bf(FBB::LocalSocketBase): Base class for tt(LocalClientSocket) and tt(LocalServerSocket). nl() Manpage(localsocketbase) bf(FBB::Log): tt(std::ostream) handling log messages.nl() Manpage(log) bf(FBB::LogBuffer): tt(std::streambuf) handling log messages.nl() Manpage(logbuffer) bf(FBB::MailHeaders): extracts mail headers from SMTP-email.nl() Manpage(mailheaders) bf(FBB::Mbuf): tt(std::streambuf) specialization for inserting messages, mainly used by tt(FBB::Mstream) objects. nl() Manpage(mbuf) bf(FBB::Milter): interfaces the sendmail mail filter facilities.nl() Manpage(milter) bf(FBB::mlm): Manipulator modifying the left margin of tt(FBB::OFoldStream) objects.nl() Manpage(mlm) bf(FBB::Mstream): Inserts messages into streams. nl() Manpage(mstream) bf(FBB::MultiStreambuf): tt(std::streambuf) specializations performing insertions to multiple tt(std::ostream) objects.nl() Manpage(multistreambuf) bf(FBB::OFdStream): stream inserting information into a device whose file descriptor is available. nl() Manpage(ofdstream) bf(FBB::OFdStreambuf): Output stream buffer initialized by a file descriptor.nl() Manpage(ofdstreambuf) bf(FBB::OFilterStreambuf): tt(std::streambuf) specialization implementing an tt(std::ostream) filtering design pattern.nl() Manpage(ofilterstreambuf) bf(FBB::OFoldStream): tt(std::ostream) using an tt(OFoldStreambuf) as its streambuf. nl() Manpage(ofoldstream) bf(FBB::OFoldStreambuf): tt(OFilterStreambuf) (tt(std::streambuf)) specialization folding text lines between left and right margins.nl() Manpage(ofoldstreambuf) bf(FBB::OHexStreambuf): tt(OHexStreambuf) (tt(std::streambuf)) specialization inserting characters into a stream by their hex values.nl() Manpage(ohexstreambuf) bf(FBB::OneKey): Single keystroke input, not requiring `Return'.nl() Manpage(onekey) bf(FBB::OSharedStream): tt(std::ostream) operations on shared memory.nl() Manpage(osharedstream) bf(FBB::Pattern): Performs regular expression pattern matching.nl() Manpage(pattern) bf(FBB::Pipe): Defines a system level pipe. nl() Manpage(pipe) bf(FBB::PrimeFactors): Performs the prime-number factorization of (BigInt) values.nl() Manpage(primefactors) bf(FBB::Process): Runs child processes, defining pipes between parents and child processes. nl() Manpage(process) bf(FBB::PtrIter): Input iterator whose dereferenced value returns a pointer rather than a reference to an element. Also offers: a tt(ptrIter) function template. nl() Manpage(ptriter) bf(FBB::Randbuffer): implements a tt(streambuf) generating random numbers. nl() Manpage(randbuffer) bf(FBB::Ranger): class creating ranges that are accepted by range-based for-loops. Also offered: a tt(ranger) function template. nl() Manpage(ranger) bf(FBB::ReadLineBuf): implements a tt(streambuf) using the Gnu tt(readline) library to allow editing an tt(std::istream)'s contents. nl() Manpage(readlinebuf) bf(FBB::ReadLineHistory): provides access to the history of lines read from a tt(ReadLineBuf). nl() Manpage(readlinehistory) bf(FBB::ReadLineStream): tt(std::istream) class using a tt(ReadLineBuf) for its tt(std::streambuf). nl() Manpage(readlinestream) bf(FBB::Redirector): Defines system level file redirection. nl() Manpage(redirector) bf(FBB::repeat): Two short extensions of the STL tt(for_each) generic algorithm. nl() Manpage(repeat) bf(FBB::Selector): Offers timed delays and multiple file I/O. nl() Manpage(selector) bf(FBB::ServerSocket): defines a socket to which clients can connect.nl() Manpage(serversocket) bf(FBB::SharedBlock): Shared memory data block info.nl() Manpage(sharedblock) bf(FBB::SharedMemory): Shared memory structure.nl() Manpage(sharedmemory) bf(FBB::SharedMutex): Mutex for shared memory.nl() Manpage(sharedmutex) bf(FBB::SharedPos): Shared Memory offset controller.nl() Manpage(sharedpos) bf(FBB::SharedSegment): Shared memory data structure.nl() Manpage(sharedsegment) bf(FBB::SharedStream): I/O operations on shared memory.nl() Manpage(sharedstream) bf(FBB::SharedStreambuf): tt(std::streambuf) interfacing to shared memory.nl() Manpage(sharedstreambuf) bf(FBB::Signal): Defines signals, allowing signal handlers to use object's data members c.q. to call object's members functions. nl() Manpage(signal) bf(FBB::SocketBase): Base class for tt(ClientSocket) and tt(ServerSocket). nl() Manpage(socketbase) bf(FBB::Stat): Determines file characteristics.nl() Manpage(stat) bf(FBB::String): Offers extended tt(std::string) functionality.nl() Manpage(string) bf(FBB::StringLine): Offers tt(operator>>) extracting lines from tt(std::istream) objects.nl() Manpage(stringline) bf(FBB::Syslogbuf): streambuf to Buffer generating bf(syslog)(3) messages. nl() Manpage(syslogbuf) bf(FBB::SyslogStream): stream to Output stream inserting bf(syslog)(3) messages. nl() Manpage(syslogbuf) bf(FBB::fswap): templates implementing memory bytes based swap functionality nl() Manpage(fswap) bf(FBB::Table): Display tables row- or column-wise.nl() Manpage(CHAR(t)able) bf(FBB::TableBuf): Display tables row- or column-wise.nl() Manpage(CHAR(t)ablebuf) bf(FBB::TableLines): Support class for the class tt(Table(Buf)).nl() Manpage(tablelines) bf(FBB::TableSupport): Support class for the class tt(Table(Buf)).nl() Manpage(tablesupport) bf(FBB::TempStream): Temporary fstream. nl() Manpage(tempstream) bf(FBB::TypeTrait): Traits class template to determine various characteristics of types.nl() Manpage(typetrait) bf(FBB::User): Determines the current user's parameters from tt(/etc/passwd).nl() Manpage(user) bf(FBB::Xpointer): sets and retrieves the X-windows pointer.nl() Manpage(xpointer) bf(FBB::X2a): x-to-Ascii conversions of any type supporting insertions into tt(o[string]stream) objects.nl() Manpage(x2a) COMMENT( bf(FBB::sequence_includes()): Template function implementing a variant of the bf(includes()) generic algorithm, not requiring sorted series. (Manpage: bf(man -e bobcat sequenceincludes)) END COMMENT) manpagesection(CATEGORIES) This section groups classes that somehow belong together. The following categories are offered: itemization( it() bf(COMMAND LINE INTERFACE AND CONFIGURATION FILES) it() bf(CONVERSIONS) it() bf(DATE AND TIME) it() bf(ERRORS AND MESSAGE HANDLING) it() bf(GENERIC ALGORITHM EXTENSIONS) it() bf(INTERNET / NETWORKING) it() bf(OPENSSL AND ENCRYPTION) it() bf(PATTERN MATCHING) it() bf(PROCESSES AND SIGNALS) it() bf(STREAMS AND FILES) it() bf(SHARED MEMORY) it() bf(TABLES) it() bf(VARIOUS OTHER CLASSES) it() bf(DEPRECATED CLASSES) ) itemization( it() bf(COMMAND LINE INTERFACE AND CONFIGURATION FILES) bf(FBB::Arg): Interfaces the command line arguments, allowing for short- and long options. The class is implemented as a tt(Singleton).nl() Manpage(arg) bf(FBB::ArgConfig): Inherits from tt(Arg) and tt(ConfigFile) allowing for options to be specified as command line options and/or configuration file options. The class is implemented as a tt(Singleton).nl() Manpage(argconfig) bf(FBB::CmdFinder): Command-function associations.nl() Manpage(cmdfinder) bf(FBB::CmdFinderBase): Base class for tt(CmdFinder).nl() Manpage(cmdfinderbase) bf(FBB::ConfigFile): Processing standard configuration files.nl() Manpage(configfile) it() bf(CONVERSIONS) bf(FBB::A2x): Ascii-to-x conversions of any type supporting extractions from tt(i[string]stream) objects. Manpage(a2x) bf(FBB::BigInt): Wrapper class around the openssl BN_ functions for unlimited integer precision arithmetic. nl() Manpage(bigint) bf(FBB::IBase64Stream): stream implementing base64 encoding and decoding, using a tt(FBB::Base64Streambuf) stream buffer.nl() Manpage(ibase64stream) bf(FBB::IBase64Streambuf): tt(FBB::IFilterStreambuf) specialization implementing base64 encoding and decoding.nl() Manpage(ibase64streambuf) bf(FBB::X2a): x-to-Ascii conversions of any type supporting insertions into tt(o[string]stream) objects.nl() Manpage(x2a) it() bf(DATE AND TIME) bf(FBB::DateTime): Manipulations with date and time values.nl() Manpage(datetime) it() bf(ERRORS AND MESSAGE HANDLING) bf(FBB::Exception): objects of this class accept tt(ostream) insertions, and are also tt(std::exception) objects.nl() Manpage(exception) bf(FBB::level): Manipulator setting the log-level of tt(FBB::Log) objects.nl() Manpage(level) bf(FBB::Log): tt(std::ostream) handling log messages.nl() Manpage(log) bf(FBB::LogBuffer): tt(std::streambuf) handling log messages.nl() Manpage(logbuffer) bf(FBB::Syslogbuf): streambuf to Buffer generating bf(syslog)(3) messages. nl() Manpage(syslogbuf) bf(FBB::SyslogStream): stream to Output stream inserting bf(syslog)(3) messages. nl() Manpage(syslogbuf) it() bf(GENERIC ALGORITHM EXTENSIONS) bf(FBB::binary_search): A modification of the STL tt(binary_search) algorithm returning the location of the searched value in a sorted series of values. nl() Manpage(binarysearch) bf(FBB::repeat): Two short extensions of the STL tt(for_each) generic algorithm. nl() Manpage(repeat) it() bf(INTERNET / NETWORKING) bf(FBB::CGI): a class implementing the facilities accessing the data made available through the Common Gateway Interface.nl() Manpage(cgi) bf(FBB::Cidr): a class testing whether IP4 Internet addresses belong to address ranges defined by Classless Inter-Domain Routing (CIDR) address block specifications.nl() Manpage(cidr) bf(FBB::ClientSocket): a socket for tcp-communication with a server.nl() Manpage(clientsocket) bf(FBB::GetHostent): Obtains tt(hostent) struct from hostname or -address. nl() Manpage(gethostent) bf(FBB::Hostname): Derived from tt(Hostent), allows the initialization from a tt(std::string), or from an tt(FBB::InetAddrress). nl() Manpage(hostname) bf(FBB::InetAddress): Base class (no public constructor) for objects representing an internet address as used with sockets. Contains address and portnumbers. nl() Manpage(inetaddress) bf(FBB::Hostent): Wrapper around the tt(hostent) struct. nl() Manpage(hostent) bf(FBB::LocalClientSocket): a Unix domain socket for tcp-communication with a Unix domain (local) server.nl() Manpage(localclientsocket) bf(FBB::LocalServerSocket): defines a Unix domain socket to which clients on the local host can connect.nl() Manpage(localserversocket) bf(FBB::LocalSocketBase): Base class for tt(LocalClientSocket) and tt(LocalServerSocket). nl() Manpage(localsocketbase) bf(FBB::MailHeaders): extracts mail headers from SMTP-email.nl() Manpage(mailheaders) bf(FBB::Milter): interfaces the sendmail mail filter facilities.nl() Manpage(milter) bf(FBB::ServerSocket): defines a socket to which clients can connect.nl() Manpage(serversocket) bf(FBB::SocketBase): Base class for tt(ClientSocket) and tt(ServerSocket). nl() Manpage(socketbase) it() bf(OPENSSL AND ENCRYPTION) bf(FBB::BigInt): Wrapper class around the openssl BN_ functions for unlimited integer precision arithmetic. nl() Manpage(bigint) bf(FBB::DecryptBuf): Decrypting information.nl() Manpage(decryptbuf) bf(FBB::DiffieHellman): Computing shared keys using the Diffie-Hellman algorithm.nl() Manpage(diffiehellman) bf(FBB::DigestBuf): Computing message digests.nl() Manpage(digestbuf) bf(FBB::EncryptBuf): Encrypting information.nl() Manpage(encryptbuf) bf(FBB::HmacBuf): Computing HMAC message digests.nl() Manpage(hmacbuf) bf(FBB::ISymCryptStream): stream implementing symmetric encryption and decryption, using a tt(FBB::ISymCryptStreambuf) stream buffer.nl() Manpage(isymcryptstream) bf(FBB::ISymCryptStreambuf): tt(FBB::IFilterStreambuf) specialization implementing symmetric cryptography.nl() Manpage(isymcryptstreambuf) it() bf(PATTERN MATCHING) bf(FBB::Glob): Obtain a list of files matching a certain pattern.nl() Manpage(glob) bf(FBB::Pattern): Performs regular expression pattern matching.nl() Manpage(pattern) it() bf(PROCESSES AND SIGNALS) bf(FBB::Fork): Defines bf(fork)(2) as part of a Template Algorithm Design Pattern. nl() Manpage(fork) bf(FBB::Process): Runs child processes, defining pipes between parents and child processes. nl() Manpage(process) bf(FBB::Signal): Defines signals, allowing signal handlers to use object's data members c.q. to call object's members functions. nl() Manpage(signal) it() bf(STREAMS AND FILES) bf(FBB::DigestBuf): Computing message digests.nl() Manpage(digestbuf) bf(FBB::IFdStream): stream extracting information from a device whose file descriptor is available. nl() Manpage(ifdstream) bf(FBB::IFdStreambuf): Input stream buffer initialized by a file descriptor.nl() Manpage(ifdstreambuf) bf(FBB::IFilterStreambuf): tt(std::streambuf) specialization implementing an tt(std::istream) filtering design pattern.nl() Manpage(ifilterstreambuf) bf(FBB::IOStream): class combining tt(std::istream) and tt(std::ostream) features. nl() Manpage(iostream) bf(FBB::IOStreambuf): tt(std::streambuf) specialization allowing combined input and output operations. nl() Manpage(iostreambuf) bf(FBB::IRandStream): stream to extract random numbers from. nl() (Manpage(irandstream)) bf(FBB::ISharedStream): tt(std::istream) operations on shared memory.nl() Manpage(isharedstream) bf(FBB::lm): Manipulator setting the left margin of tt(FBB::OFoldStream) objects.nl() Manpage(lm) bf(FBB::Mbuf): tt(std::streambuf) specialization for inserting messages, mainly used by tt(FBB::Mstream) objects. nl() Manpage(mbuf) bf(FBB::mlm): Manipulator modifying the left margin of tt(FBB::OFoldStream) objects.nl() Manpage(mlm) bf(FBB::Mstream): Inserts messages into streams. nl() Manpage(mstream) bf(FBB::MultiStreambuf): tt(std::streambuf) specializations performing insertions to multiple tt(std::ostream) objects.nl() Manpage(multistreambuf) bf(FBB::OFdStream): stream inserting information into a device whose file descriptor is available. nl() Manpage(ofdstream) bf(FBB::OFdStreambuf): Output stream buffer initialized by a file descriptor.nl() Manpage(ofdstreambuf) bf(FBB::OFilterStreambuf): tt(std::streambuf) specialization implementing an tt(std::ostream) filtering design pattern.nl() Manpage(ofilterstreambuf) bf(FBB::OFoldStream): tt(std::ostream) using an tt(OFoldStreambuf) as its streambuf. nl() Manpage(ofoldstream) bf(FBB::OFoldStreambuf): tt(OFilterStreambuf) (tt(std::streambuf)) specialization folding text lines between left and right margins.nl() Manpage(ofoldstreambuf) bf(FBB::OHexStreambuf): tt(OHexStreambuf) (tt(std::streambuf)) specialization inserting characters into a stream by their hex values.nl() Manpage(ohexstreambuf) bf(FBB::OSharedStream): tt(std::ostream) operations on shared memory.nl() Manpage(osharedstream) bf(FBB::Pipe): Defines a system level pipe. nl() Manpage(pipe) bf(FBB::Randbuffer): implements a tt(streambuf) generating random numbers. nl() Manpage(randbuffer) bf(FBB::ReadLineBuf): implements a tt(streambuf) using the Gnu tt(readline) library to allow editing an tt(std::istream)'s contents. nl() Manpage(readlinebuf) bf(FBB::ReadLineHistory): provides access to the history of lines read from a tt(ReadLineBuf). nl() Manpage(readlinehistory) bf(FBB::ReadLineStream): tt(std::istream) class using a tt(ReadLineBuf) for its tt(std::streambuf). nl() Manpage(readlinestream) bf(FBB::Redirector): Defines system level file redirection. nl() Manpage(redirector) bf(FBB::Selector): Offers timed delays and multiple file I/O. nl() Manpage(selector) bf(FBB::SharedStream): I/O operations on shared memory.nl() Manpage(sharedstream) bf(FBB::SharedStreambuf): tt(std::streambuf) interfacing to shared memory.nl() Manpage(sharedstreambuf) bf(FBB::Stat): Determines file characteristics.nl() Manpage(stat) bf(FBB::TempStream): Temporary fstream. nl() Manpage(tempstream) it() bf(SHARED MEMORY) bf(FBB::ISharedStream): tt(std::istream) operations on shared memory.nl() Manpage(isharedstream) bf(FBB::OSharedStream): tt(std::ostream) operations on shared memory.nl() Manpage(osharedstream) bf(FBB::SharedBlock): Shared memory data block info.nl() Manpage(sharedblock) bf(FBB::SharedMemory): Shared memory structure.nl() Manpage(sharedmemory) bf(FBB::SharedMutex): Mutex for shared memory.nl() Manpage(sharedmutex) bf(FBB::SharedPos): Shared Memory offset controller.nl() Manpage(sharedpos) bf(FBB::SharedSegment): Shared memory data structure.nl() Manpage(sharedsegment) bf(FBB::SharedStream): I/O operations on shared memory.nl() Manpage(sharedstream) bf(FBB::SharedStreambuf): tt(std::streambuf) interfacing to shared memory.nl() Manpage(sharedstreambuf) it() bf(TABLES) bf(FBB::Align): Specifies tt(Table(Buf)) column and element alignments.nl() Manpage(align) bf(FBB::Table): Display tables row- or column-wise.nl() Manpage(CHAR(t)able) bf(FBB::TableBuf): Display tables row- or column-wise.nl() Manpage(CHAR(t)ablebuf) bf(FBB::TableLines): Support class for the class tt(Table(Buf)).nl() Manpage(tablelines) bf(FBB::TableSupport): Support class for the class tt(Table(Buf)).nl() Manpage(tablesupport) it() bf(VARIOUS OTHER CLASSES) bf(FBB::BinOps): A series of function templates implementing binary operators for classes that implement the matching binary assignment operators themselves. nl() Manpage(binops) bf(FBB::fswap): templates implementing memory bytes based swap functionality nl() Manpage(fswap) bf(FBB::Indent): Class and manipulators performing text indentation. nl() Manpage(indent) bf(FBB::Hash...): Various template classes implementing mapping containers using hashing.nl() Manpage(hash) bf(FBB::OneKey): Single keystroke input, not requiring `Return'.nl() Manpage(onekey) bf(FBB::PrimeFactors): Performs the prime-number factorization of (BigInt) values.nl() Manpage(primefactors) bf(FBB::PtrIter): Input iterator whose dereferenced value returns a pointer rather than a reference to an element. Also offers: a tt(ptrIter) function template. nl() Manpage(ptriter) bf(FBB::Ranger): class creating ranges that are accepted by range-based for-loops. Also offered: a tt(ranger) function template. nl() Manpage(ranger) bf(FBB::String): Offers extended tt(std::string) functionality.nl() Manpage(string) bf(FBB::StringLine): Offers tt(operator>>) extracting lines from tt(std::istream) objects.nl() Manpage(stringline) bf(FBB::TypeTrait): Traits class template to determine various characteristics of types.nl() Manpage(typetrait) bf(FBB::User): Determines the current user's parameters from tt(/etc/passwd).nl() Manpage(user) bf(FBB::Xpointer): sets and retrieves the X-windows pointer.nl() Manpage(xpointer) it() bf(DEPRECATED CLASSES) Deprecated classes should no longer be used. Their functionality is better provided by other classes. The deprecated classes are no longer maintained. bf(FBB::AutoPtr): replacement: bf(C++-11) tt(std::shared_ptr) and tt(unique_ptr).nl() bf(FBB::Errno): replacement: tt(FBB::Exception).nl() bf(FBB::FnWrap): replacement: bf(C++-11) lambda functions.nl() bf(FBB::for_each): replacement: bf(C++-11) lambda functions.nl() bf(FBB::Msg): replacement: tt(FBB::Mstream).nl() bf(FBB::RefCount): replacement: bf(C++-11) tt(std::shared_ptr) and tt(unique_ptr).nl() ) manpagesection(LINKING) To link programs against the shared bf(Bobcat) library (e.g., tt(libbobcat3.so)) it is usually sufficient to merely specify tt(-lbobcat). E.g., verb( g++ --std=c++11 main.cc -lbobcat ) Due to a change in library handling by the linker (cf. lurl(http://fedoraproject.org/wiki/UnderstandingDSOLinkChange) and lurl(https://wiki.debian.org/ToolChain/DSOLinking)), implemented in 2013, libraries that are indirectly required are no longer automatically linked to your program. With some classes (e.g., tt(BigInt)) the tt(libcrypto) library must also be specified, and programs using such classes must be linked against tt(bobcat) and tt(crypto): verb( g++ --std=c++11 main.cc -lbobcat -lcrypto ) Man-pages of classes requiring additional libraries mention these additional libraries in their bf(SYNOPSIS) sections. When using em(static) linking, the situation is slightly more problematic, and no general rule can be provided here. To create a statically linked program the flag tt(-static) must be provided, but in addition the tt(-pthread) flag must often be specified as well. If, when statically linking your program, undefined references to tt(pthread_...) identifiers are reported, then that is a sure sign that you need to provide the tt(-pthread) flag as well. When using static linking additional libraries, not specified at the man-pages, may also be required. E.g., when using the tt(Xpointer) class and using static linking, the command becomes: verb( g++ main.cc -static -pthread -lbobcat -lX11 -lxcb -lXdmcp -lXau ) When encountering undefined references when using static linking missing libraries may be suggested by the linker or by its error messages. Alternatively, the missing libraries may be found by searching the Internet. manpagefiles() itemization( itb(/usr/include/bobcat/) itb(/usr/lib/libbobcat.*) (shared, static libraries) ) manpageseealso() The individual bf(bobcat/3) header files, with man-pages accessible using tt(man -e bobcat class) (all lowercase names) manpagebugs() No Reported Bugs. includefile(include/trailer) bobcat-3.19.01/documentation/man/pattern.yo0000644000175000017500000002504212222576535017571 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Pattern)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Pattern matcher) manpagename(FBB::Pattern)(Performs RE pattern matching) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(Pattern) objects may be used for Regular Expression (RE) pattern matching. The class is a wrapper around the bf(regcomp)(3) family of functions. By default it uses `extended regular expressions', requiring you to escape multipliers and bounding-characters when they should be interpreted as ordinary characters (i.e., tt(*, +, ?, ^, $, |, (, ), [, ], {, }) should be escaped when used as literal characters). The bf(Pattern) class supports the use of the following (Perl-like) special escape sequences: nl() \b - indicating a word-boundary nl() \d - indicating a digit (tt([[:digit:]])) character nl() \s - indicating a white-space (tt([:space:])) character nl() \w - indicating a word (tt([:alnum:])) character The corresponding capitals (e.g., bf(\W)) define the complementary character sets. The capitalized character set shorthands are not expanded inside explicit character-classes (i.e., tt([ ... ]) constructions). So tt([\W]) represents a set of two characters: tt(\) and tt(W). As the backslash (tt(\)) is treated as a special character it should be handled carefully. bf(Pattern) converts the escape sequences tt(\d \s \w) (and outside of explicit character classes the sequences tt(\D \S \W)) to their respective character classes. All other escape sequences are kept as is, and the resulting regular expression is offered to the pattern matching compilation function bf(regcomp)(3). This function will again interpret escape sequences. Consequently some care should be exercised when defining patterns containing escape sequences. Here are the rules: itemization( it() Special escape sequences (like tt(\d)) are converted to character classes. E.g., verb( --------------------------------------------------------- Specify: Converts to: regcomp uses: Matches: --------------------------------------------------------- \d [[:digit:]] [[:digit:]] 3 --------------------------------------------------------- ) it() Ordinary escape sequences (like tt(\x)) are kept as-is. E.g., verb( --------------------------------------------------------- Specify: Converts to: regcomp uses: Matches: --------------------------------------------------------- \x \x x x --------------------------------------------------------- ) it() To specify a literal escape sequence, it must be written twice. E.g., verb( --------------------------------------------------------- Specify: Converts to: regcomp uses: Matches: --------------------------------------------------------- \\x \\x \x \x --------------------------------------------------------- ) ) includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(TYPEDEF) itemization( itb(Pattern::Position) A nested type representing the offsets of the first character and the offset beyond the last character of the matched text or indexed subexpression, defined as tt(std::pair). ) manpagesection(CONSTRUCTORS) itemization( itb(Pattern()) The default constructor defines no pattern, but is available as a placeholder for, e.g., containers requiring default constructors. A bf(Pattern) object thus constructed cannot be used to match patterns, but can be the em(lvalue) in assignments where another bf(Pattern) object is the em(rvalue). However, it can receive a pattern using the member bf(setPattern()) (see below). An bf(FBB::Exception) object is thrown if the object could not be constructed. itb(Pattern(std::string const &pattern, bool caseSensitive = true, size_t nSub = 10, int options = REG_EXTENDED | REG_NEWLINE)) This constructor compiles tt(pattern), preparing the bf(Pattern) object for pattern matches. The second parameter determines whether case sensitive matching will be used (the default) or not. Subexpressions are defined by parentheses pairs. Each matching pair defines a subexpression, where the order-number of their opening parentheses determines the subexpression's index. By default at most 10 subexpressions are recognized. The em(options) flags may be: REG_EXTENDED: nl() Use POSIX Extended Regular Expression syntax when interpreting regex. If not set, POSIX Basic Regular Expression syntax is used. REG_NOSUB: nl() Support for substring addressing of matches is not required. The nmatch and pmatch parameters to regexec are ignored if the pattern buffer supplied was compiled with this flag set. REG_NEWLINE: nl() Match-any-character operators don't match a newline. A non-matching list ([^...]) not containing a newline does not match a newline. Match-beginning-of-line operator (^) matches the empty string immediately after a newline, regardless of whether eflags, the execution flags of regexec, contains REG_NOTBOL. Match-end-of-line operator ($) matches the empty string immediately before a newline, regardless of whether eflags contains REG_NOTEOL. ) tt(Pattern) offers copy and move constructors. manpagesection(MEMBER FUNCTIONS) All members of bf(std::ostringstream) and bf( std::exception) are available, as bf(Pattern) inherits from these classes. itemization( itb(std::string before() const) Following a successful match, bf(before()) returns the text before the matched text. itb(std::string beyond() const) Following a successful match, bf(beyond()) returns the text beyond the matched text. itb(size_t end() const) Returns the number of matched elements (text and subexpressions). bf(end()) is the lowest index value for which bf(position()) returns two tt(std::string::npos) values (see the bf(position()) member function, below). itb(void match(std::string const &text, int options = 0)) Match a string with a pattern. If the text could not be matched, an bf(Exception) exception is thrown , using bf(Pattern::match()) as its prefix-text. Options may be: REG_NOTBOL: nl() The match-beginning-of-line operator always fails to match (but see the compilation flag REG_NEWLINE above) This flag may be used when different portions of a string are passed to regexec and the beginning of the string should not be interpreted as the beginning of the line. REG_NOTEOL: nl() The match-end-of-line operator always fails to match (but see the compilation flag REG_NEWLINE) itb(std::string matched() const) Following a successful match, this function returns the matched text. itb(std::string const &pattern() const) This member function returns the pattern that is offered to bf(regcomp)(3). It returns the contents of a tt(static) string that is overwritten at each construction of a bf(Pattern) object and at each call of the tt(setPattern()) member function. itb(Pattern::Position position(size_t index) const) With em(index == 0) the fully matched text is returned (identical to tt(matched())). Other index values return the corresponding subexpressions. bf(std::string::npos, std::string::npos) is returned if index is at least bf(end()) (which may happen at index value 0). itb(void setPattern(std::string const &pattern, bool caseSensitive = true, size_t nSub = 10, int options = REG_EXTENDED | REG_NEWLINE)) This member function installs a new compiled tt(pattern) in its bf(Pattern) object. This member's parameters are identical to the second constructor's parameters. Refer to that constructor for details about the parameters. Like the constructor, an bf(FBB::Exception) exception is thrown if the new pattern could not be compiled. itb(void swap(Pattern &other)) The contents of the current object and the tt(other) object are swapped. ) manpagesection(OVERLOADED OPERATORS) itemization( itb(Pattern &operator=(Pattern &other)) A standard overloaded assignment operator. itb(std::string operator[](size_t index) const) Returns the matched text (for index 0) or the text of a subexpression. An empty string is returned for index values which are at least bf(end()). itb(Pattern &operator<<(int matchOptions)) Defines match-options to be used with the following overloaded operator. itb(bool operator<<(std::string const &text)) Performs a bf(match(text, matchOptions)) call, catching any exception that might be thrown. If no em(matchOptions) were set using the above overloaded operator, none are used. The options set this way are not `sticky': when necessary, they have to be re-inserted before each new pattern matching. The function returns bf(true) if the matching was successful, bf(false) otherwise. ) manpagesection(EXAMPLE) verbinclude(../../pattern/driver/driver.cc) manpagefiles() em(bobcat/pattern) - defines the class interface manpageseealso() bf(bobcat)(7), bf(regcomp)(3), bf(regex)(3), bf(regex)(7) manpagebugs() Using tt(Pattern) objects as static data members of classes (or as global objects) is potentially dangerous. If the object files defining these static data members are stored in a dynamic library they may not be initialized properly or timely, and their eventual destruction may result in a segmentation fault. This is a well-known problem with static data, see, e.g., tt(http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.15). In situations like this prefer the use of a (shared, unique) pointer to a tt(Pattern), initialzing the pointer when, e.g., first used. includefile(include/trailer) bobcat-3.19.01/documentation/man/ofdstream.yo0000644000175000017500000000364412222576535020104 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::OFdStream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (File Descriptor Output Stream) manpagename(FBB::Ofdstream)(Output Stream initialized by a File Descriptor) manpagesynopsis() bf(#include )nl() manpagedescription() bf(FBB::OFdStream) objects may be used to insert information into a device whose file descriptor is available. File descriptors are not defined within the context of bf(C++), but they can be used on operating systems that support the concept. Realize that using file descriptors introduces operating system dependencies. Note that em(sockets) can be used as file descriptors. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::ostream) manpagesection(CONSTRUCTORS) itemization( itb(OFdStream(int fd, size_t n = 1)) The constructor initializes the object to write to descriptor tt(fd), using a buffer of size tt(n), by default having size 1. ) The copy constructor is not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::ostream) are available, as bf(FBB::OFdStream) inherits from this class. There are no additional members. manpagesection(EXAMPLE) See the bf(clientsocket)(3bobcat) man-page for an example showing how to use tt(OFdStream). manpagefiles() em(bobcat/ofdstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ifdstream)(3bobcat), bf(ofdstreambuf)(3bobcat) manpagebugs() The tt(OFdStream) object uses a tt(OFdStreamBuf) for its tt(std::streambuf). This buffer is associated with the file descriptor passed to tt(OFdStream)'s constructor. When the tt(OFdStream) object goes out of scope the device (file, socket, etc.) to which the file descriptor that was passed to tt(OFdStream)'s constructor is em(not) closed. includefile(include/trailer) bobcat-3.19.01/documentation/man/lm.yo0000644000175000017500000000431512222576535016524 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::lm)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (OFoldStream manipulator) manpagename(FBB::lm)(Manipulator setting left margins of OFoldStream objects) manpagesynopsis() bf(#include ) or nl() bf(#include ) nl() Linking option: tt(-lbobcat) manpagedescription() The tt(lm) class implements a manipulator that can be inserted into tt(OFoldStream) objects to set the stream's left margin to a requested value. Depending on the tab-setting of the tt(OFoldStream) the inserted value represents the number of blank space characters or the number of tab-characters that will be used for the left margin. The request will be processed at the next newline character or tt(std::flush) or tt(std::endl) manipulator that is inserted into the stream. If a line is still once an tt(lm) object and a tt(flush) manipulator are inserted into the stream then the new left margin will be effective at the next word inserted into that line (cf., the example section below). A em(bad_cast) exception is thrown when the manipulator is inserted into an tt(ostream) that is not using a tt(OFoldStreambuf) buffer. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTOR) itemization( itb(lm(size_t newValue)) ) The standard copy constructor is available. manpagesection(MEMBER FUNCTIONS) There are no public or protected member functions in this class. manpagesection(EXAMPLE) verb( #include #include using namespace std; using namespace FBB; int main() { OFoldStream out(cout, 0, 80); out << "hello world (left margin is 0)" << lm(4) << "\n" "this uses a 4 character wide left margin\n" << lm(0) << flush << "at column 0 again\n"; return 0; } ) manpagefiles() em(bobcat/lm) - defines the class interface manpageseealso() bf(bobcat)(7), bf(manipulators)(3bobcat), bf(mlm)(3bobcat), bf(ofoldstream)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/tablelines.yo0000644000175000017500000000255112222576535020236 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::TableLines)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz)(Table support class) manpagename(FBB::TableLines)(A TableSupport specialization writing horizontal separation lines) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() This class is a specialization of tt(FBB::TableSupport) and can be used to write horizontal (and vertical) line separators in tables generated by tt(Table) or tt(TableBuf) objects. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::TableSupport) manpagesection(CONSTRUCTORS) The default, copy and move constructors are available. manpagesection(OVERLOADED OPERATORS) The copy and move assignment operators are available. manpagesection(MEMBER FUNCTIONS) All public members of tt(TableSupport) are available. The reader should refer to the bf(tablesupport)(3bobcat) man-page for details. manpagesection(EXAMPLE) verbinclude(../../table/driver/driver.cc) manpagefiles() em(bobcat/tableLines) - defines the class interface manpageseealso() bf(bobcat)(7), bf(align)(3bobcat), bf(table)(3bobcat), bf(tablebuf)(3bobcat), bf(tablesuppoer)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/ibase64streambuf.yo0000644000175000017500000000656212222576535021270 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::IBase64Streambuf)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz) (Base64 converting Stream Buffer) manpagename(FBB::IBase64Streambuf) (Input Filtering stream buffer doing base64 conversion) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() The information made available by bf(IBase64Streambuf) objects has been subject to base64 encoding or decoding. The information to be converted is made available to bf(IBase64Streambuf) object via tt(std::istream) objects. The tt(class IBase64Streambuf) is a class template, using a tt(FBB::CryptType) template non-type parameter. Objects of the class tt(FBB::IBase64Streambuf) base64 encode the information they receive, objects of the class tt(FBB::IBase64Streambuf) base64 decode the information they receive. See also section bf(ENUMERATION) below. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::IFilterStreambuf) manpagesection(MEMBER FUNCTIONS) All members of bf(FBB::IFilterStreambuf) are available, as bf(IBase64Streambuf) inherits from this class. Overloaded move and/or copy assignment operators are not available. manpagesection(ENUMERATION) bf(IBase64Streambuf) objects either base64 encode or decode information. bf(IBase64Streambuf) objects of the class bf(FBB::IBase64Streambuf) base64 encode the data they receive, bf(IBase64Streambuf) objects of the class bf(FBB::IBase64Streambuf) base64 decode the data they receive. The values tt(ENCRYPT) and tt(DECRYPT) are defined in the tt(enum CryptType), which is defined in the tt(FBB) namespace. manpagesection(CONSTRUCTOR) itemization( itb(IBase64Streambuf(std::istream &in, size_t bufSize = 1000)) This constructor initializes the streambuf. - tt(IBase64Streambuf) objects perform base64 encoding;nl() - tt(IBase64Streambuf) objects perform base64 decoding;nl() - tt(IBase64Streambuf) objects obtain the bytes to encode or decode from tt(std::istream &in);nl() - The tt(IFilterStreambuf) base class is initialized with a buffer of size tt(bufSize), using a lower bound of 100. ) ) Copy- and move constructors are not available. manpagesection(EXAMPLE) The example shows the construction of tt(IBase64Streambuf) objects tt(encode) which are used to initialize a tt(std::istream) object. The information read from this tt(istream) is base64 encoded. tt(IBase64Streambuf) objects (tt(decode) reads base64 encoded information from tt(std::istream) objects and decodes it again. The tt(std::istream din) object is initialized with the tt(IBase64Streambuf) object, and its contents is sent to tt(std::cout). The information that is presented at tt(std::cin) and that appears at tt(std::cout) should be identical. verbinclude(../../ibase64streambuf/driver/driver.cc) manpagefiles() em(bobcat/ibase64streambuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(isymcryptstreambuf)(3bobcat), bf(ibase64stream)(3bobcat), bf(ifilterstreambuf)(3bobcat), bf(ofilterstreambuf)(3bobcat), bf(std::streambuf). manpagebugs() None reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/clientsocket.yo0000644000175000017500000001122412222576535020600 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::ClientSocket)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Client Socket) manpagename(FBB::ClientSocket) (Client Socket connecting to a Server in the Internet) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() An bf(FBB::ClientSocket) may be constructed to connect to some server process in the internet. The socket made available by the bf(FBB:ClientSocket) may be used to initialize a bf(std::istream) and/or bf(std::ostream). The bf(std::istream) is used to read information from the server process to which the bf(FBB::ClientSocket) connects, The bf(std::ostream) is used to send information to the server process to which the bf(FBB::ClientSocket) connects. Since a socket may be considered a em(file descriptor) the avaiable bf(FBB::IFdStream), bf(FBB::IFdStreamBuf), bf(FBB::OFdStream), and bf(FBB::OFdStreamBuf) classes may be used profitably here. Note that having available a socket does not mean that this defines the communication protocol. It is (still) the responsibility of the programmer to comply with an existing protocol or to implement a tailor-made protocol. The latter situation implies that the sequence of input- and output operations is defined by the programmer. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::SocketBase) manpagesection(CONSTRUCTOR) itemization( itb(ClientSocket(std::string const &host, uint16_t port)) This constructor initializes an bf(FBB::ClientSocket) object, preparing it for a connection to the specified port at the given host. An bf(FBB::Exception) is thrown if the socket could not be constructed. The construction of the socket does not mean that a connection has actually been established. In order to connect to the server, the member bf(connect()) (see below) should be used. ) The copy constructor is not available. manpagesection(MEMBER FUNCTIONS) All members of bf(FBB::SocketBase) (and thus of bf(FBB::InetAddress)) are available, as bf(FBB::ClientSocket) inherits from these classes. itemization( itb(int connect()) This member returns a socket that can be used to communicate with the server process. An bf(FBB::Exception) exception is thrown if the connection could not be established or if the bf(SocketBase) base class could not properly be constructed. ) manpagesection(EXAMPLE) See also the bf(serversocket)(3bobcat) example. verb( #include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) { cerr << "Provide servername and port number\n"; return 1; } size_t port = A2x(argv[2]); ClientSocket client(argv[1], port); int fd = client.connect(); string line; cout << "Connecting to socket " << fd << endl << "address = " << client.dottedDecimalAddress() << ", " << endl << "communication through port " << client.port() << endl; IFdStream in(fd); // stream to read from OFdStream out(fd); // stream to write to while (true) { // Ask for a textline, stop if cout << "? "; // empty / none if (!getline(cin, line) || line.length() == 0) return 0; cout << "Line read: " << line << endl; // Return the line to the server out << line.c_str() << endl; cout << "wrote line\n"; getline(in, line); // Wait for a reply from the server cout << "Answer: " << line << endl; } return 0; } catch (Exception const &err) { cerr << err.what() << "\n" << "Can't connect to " << argv[1] << ", port " << argv[2] << endl; return 1; } ) manpagefiles() em(bobcat/clientsocket) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ifdstream)(3bobcat), bf(ifdstreambuf)(3bobcat), bf(inetaddress)(3bobcat), bf(localclientsocket)(3bobcat), bf(ofdstream)(3bobcat), bf(ofdstream)(3bobcat), bf(serversocket)(3bobcat), bf(socketbase)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/logbuffer.yo0000644000175000017500000001313112222576535020063 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::LogBuffer)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (log messages stream buffer) manpagename(FBB::LogBuffer)( bf(std::streambuf) handling log messages) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::LogBuffer) is a class derived from bf(std::streambuf) handling log messages. The stream to log to, timestamps and log-levels can be configured both at construction time and beyond. The bf(FBB::LogBuffer) may be used to initialize a bf(std::ostream). includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(ENUMERATION) The enumeration bf(TimeStamps) is defined in the namespace bf(FBB) to be used when initializing bf(FBB::LogBuffer) objects. It has the following values: itemization( itb(NOTIMESTAMPS) Log-messages will not have timestamps prepended to them. itb(TIMESTAMPS) Log-messages will have timestamps prepended to them. ) manpagesection(CONSTRUCTORS) itemization( itb(LogBuffer(TimeStamps timestamps = TIMESTAMPS, bool active = true, char const *delim = " ")) This constructor constructs an bf(FBB::LogBuffer) object writing its log-messages to bf(std::cerr). If the bf(active) parameter is initialized to bf(false) no messages will be logged until the buffer's activity is switched on (see bf(setActive()) below). The parameter bf(delim) is inserted immediately beyond the time stamp. If a delimiter is inappropriate, an empty string or a 0-pointer may be specified. When bf(stamps == FBB::NOTIMESTAMPS delim) is ignored. A time stamp consists of the month, the day number of the month and the (local) time of the current message, as usually appearing in messages in tt(/var/log) files. E.g., tt(Aug 5 13:52:23). itb(LogBuffer(std::ostream &stream, TimeStamps timestamps = TIMESTAMPS, bool active = true, char const *delim = " ")) This constructor constructs an bf(FBB::LogBuffer) object writing its log-messages to the stream used to initialize its bf(stream) parameter. If the bf(active) parameter is initialized to bf(false) no messages will be logged until the buffer's activity is switched on (see bf(setActive()) below). The parameter bf(delim) is inserted immediately beyond the time stamp. If a delimiter is inappropriate, an empty string or a 0-pointer may be specified. When bf(stamps == FBB::NOTIMESTAMPS delim) is ignored. A time stamp consists of the month, the day number of the month and the (local) time of the current message, as usually appearing in messages in tt(/var/log) files. E.g., tt(Aug 5 13:52:23). ) The copy constructor is not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::LogBuffer) inherits from this class. itemization( itb(void setStream(std::ostream &stream)) This member may be used to switch the stream to log to. It is the responsibility of the programmer to ensure that the external stream remains available for as long as log-messages are inserted into it. itb(int overflow(int c)) This member em(overrides) the bf(std::streambuf) member. It is called by tt(std::ostream) objects using bf(OFdStreambuf). It calls tt(sync()), an then it puts the next available character into the buffer. It returns the inserted character. itb(int sync()) This member em(overrides) the bf(std::streambuf) member. It writes the buffer to the device associated with the file descriptor, and returns 0. itb(void setStream(bool active)) The member function (de)activates logging. The argument bf(true) activates logging, the argument bf(false) deactivates it. itb(void settimestamp(FBB::TimeStamps timestamps, char const *delim = " ")) The member function (de)activates time stamp prepending. Use the value bf(FBB::TIMESTAMPS) to prepend time stamps, bf(FBB::NOTIMESTAMPS) suppresses time stamps. A time stamp consists of the month, the day number of the month and the (local) time of the current message, as usually appearing in messages in tt(/var/log) files. E.g., tt(Aug 5 13:52:23). The parameter bf(delim) is inserted immediately beyond the time stamp. If a delimiter is inappropriate, an empty string or a 0-pointer may be specified. When bf(stamps == FBB::NOTIMESTAMPS delim) is ignored. itb(void setEmpty(bool empty)) This member may be called to ensure that a timestamp is inserted before the next insertion. It is called as bf(setEmpty(true)) when a newline character (tt(\n)) is inserted, ensuring that another timestamp is prepended before the next insertion. ) manpagesection(PROTECTED MEMBER FUNCTION) The member listed in this section implements the tasks of the comparably named virtual function in the class's private interface. This separates the redefinable interface from the user-interface. The class bf(LogBuffer) can, in accordance with Liskov's Substitution Principle, be used as a tt(std:streambuf); but it also offers a facility for classes deriving from bf(LogBuffer). This facility is listed here. itemization( itb(int pSync()) The contents of the bf(LogBuffer)'s internal buffer is flushed. ) manpagesection(EXAMPLE) verbinclude(../../logbuffer/driver/driver.cc) manpagefiles() em(bobcat/logbuffer) - defines the class interface manpageseealso() bf(bobcat)(7), bf(log)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/fork.yo0000644000175000017500000001462112222576535017056 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Fork)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Template Design Pattern around fork(2)) manpagename(FBB::Fork) (Implements bf(fork)(2) using the Template Design Pattern) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::Fork) objects may be used to implement the bf(fork)(2) call as part of the Template Algorithm Design Pattern. The class was designed as a virtual base class for classes implementing the essential parts of the forking process. The class is a virtual base class. Derived classes em(must) implement the members bf(childProcess()) and bf(parentProcess()) as part of the `Template Method Design Pattern' (see Gamma em(et al.), 1995). Terminating child processes send bf(SIGCHLD) signals to their parents. The bf(C) library offers the following em(macros) to analyze the em(status) values received by the parent process using a bf(wait)(2) or bf(waitpid)(2) system call: itemization( itb(int WIFEXITED(int status)) This macro returns a nonzero value if the child process terminated normally with `exit' or `_exit'. itb(int WEXITSTATUS(int status)) If `WIFEXITED' is true of `tt(status)', this macro returns the low-order 8 bits of the exit status value from the child process. itb(int WIFSIGNALED(int status)) This macro returns a nonzero value if the child process terminated because it received a signal that was not handled. itb(int WTERMSIG(int status)) If `WIFSIGNALED' is true of `tt(status)', this macro returns the signal number of the signal that terminated the child process. itb(int WCOREDUMP(int status)) This macro returns a nonzero value if the child process terminated and produced a core dump. itb(int WIFSTOPPED(int status)) This macro returns a nonzero value if the child process is stopped. itb(int WSTOPSIG(int status)) If `WIFSTOPPED' is true of `tt(status)', this macro returns the signal number of the signal that caused the child process to stop. ) includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) itemization( itb(Fork()) This is the only available constructor. ) Note that there is no copy constructor. manpagesection(DESTRUCTOR) itemization( itb(virtual ~Fork()) Derived classes may define their own destructor, which is called when the bf(~Fork()) destructor is activated. ) manpagesection(MEMBER FUNCTIONS) itemization( itb(void fork()) Performs the actual forking. It is implemented in such a way that the corresponding parent- and child- processes are activated from virtual members of bf(FBB::Fork). If the forking operation fails, an bf(FBB::Exception) exception is thrown. ) manpagesection(PROTECTED MEMBER FUNCTIONS) itemization( itb(virtual void childProcess() = 0) This member em(must) be implemented by derived classes. It defines the actions that are performed by the child process, following the bf(fork)(2) system call. Just before bf(childProcess()) is called, bf(childRedirections()) (see below) has been executed. The tt(childProcess()) function should terminate the child process. A good way to do this is to throw an exeption which is caught by tt(main())'s function try block. Terminating a process using bf(exit)(2) is deprecated in bf(C++). itb(virtual void childRedirections()) This function em(may) be redefined in derived classes to set up the redirections that are necessary to communicate with the parent process. See also the classes bf(redirector)(3bobcat), bf(pipe)(3bobcat), bf(ipipe)(3bobcat) and bf(opipe)(3bobcat). By default, bf(childRedirections()) does nothing. itb(virtual void parentProcess() = 0) This member em(must) be implemented by derived classes. It defines the actions that are performed by the parent process, following the bf(fork)(2) system call. Just before bf(parentProcess()) is called, bf(parentRedirections()) (see below) has been executed. itb(virtual void parentRedirections()) This function em(may) be redefined in derived classes to set up the redirections that are necessary to communicate with, e.g., the parent. See, e.g., the classes bf(redirector)(3bobcat), bf(pipe)(3bobcat), bf(ipipe)(3bobcat) and bf(opipe)(3bobcat). By default, bf(parentRedirections()) does nothing. itb(pid_t pid() const) Returns the child's process id in the parent's code (i.e., in the bf(parent-)members below), and 0 in the child's code (i.e., in the bf(child-)members below). Note that the value of bf(pid()) is bf(undefined) when called em(before) the member bf(fork()) has been called. itb(void prepareDaemon() const) Prepares for a daemon childprocess. This function may (should) be called from bf(childProcess()) to ensure that the child process changes its current working directory to the root (/) directory, thus freeing up mount points; that the child process starts a new session/process group to allow the parent (group leader) to kill all its processes without terminating the daemon; and makes sure that the child process closes and reopens the standard streams by associating them with tt(/dev/null) to prevent ghost input and output actions from interfering with the daemon's actions. An tt(FBB::Exception) is thrown if changing directory to the root directory fails. itb(int waitForChild()) This member may be called by bf(parentProcess()) to wait for the completion of the child-process. The return value (exit-code) of the child process is returned as a value between 0 and 255. If the child process terminates before the completion of the parent process, then bf(waitForChild()) should be called to prevent em(zombies) from occurring. Alternatively, the parent process may terminate (e.g., using bf(exit)(2)) while the child process is still alive. This is the normal way to create a em(daemon) process. ) manpagesection(EXAMPLE) verbinclude(../../fork/driver/driver.cc) manpagefiles() em(bobcat/fork) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ipipe)(3bobcat), bf(fork)(2), bf(opipe)(3bobcat), bf(pipe)(3bobcat), bf(redirector)(3bobcat), bf(wait)(2), bf(waitpid)(2) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/sharedstreambuf.yo0000644000175000017500000001367612242117617021277 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::SharedStreambuf)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz) (Error handler) manpagename(FBB::SharedStreambuf)(streambuf interfacing to shared memory) manpagesynopsis() bf(#include )nl() Linking option: tt(-lpthread -lbobcat) manpagedescription() This class implements a specialization of the bf(std::streambuf) class, allowing stream classes (tt(std::istream, std::ostream, FBB::ISharedStream, FBB::OSharedStream) and tt(FBB::SharedStream) to perform I/O operations on shared memory. bf(FBB::SharedStreambuf) objects interface to an tt(FBB::SharedStream) objects. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf, FBB::SharedEnum__) (cf. bf(sharedmemory(3bobcat)) for a description of the latter class). manpagesection(CONSTRUCTORS) itemization( itb(SharedStreambuf()) The default constructor defines a stub bf(SharedStreambuf) object that cannot immediately be used to access shared memory. To use it, its member tt(setMemory) must first be called. itb(SharedStreambuf(size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::in | std::ios::out, size_t access = 0600)) This constructor creates a shared memory segment having a capacity of at least tt(maxSize * sizeUnit) bytes. By default, the shared memory segment is opened for reading and writing. Different from the open modes used for file streams, creating a shared memory stream with open modes tt(ios::in | ios::out) is OK. In this case the shared memory segment is created and once information has been written to the shared memory it can also be read again. The shared memory's access rights are defined by the tt(access) parameter, using the well-known (bf(chmod)(1)) way to define the access rights for the owner, the group and others, using octal digits. If construction succeeds the shared memory is ready for use. If construction fails, an tt(FBB::Exception) is thrown. itb(SharedStreambuf(int id, std::ios::openmode openMode = std::ios::in | std::ios::out)) This constructor connects to a shared memory segment having ID tt(id). If construction succeeds the shared memory is ready for use. If construction fails (e.g., no shared memory segment having ID tt(id) exists, an tt(FBB::Exception) is thrown. Specifying the tt(ios::trunc) flag or specifying tt(ios::out) without also specifying tt(ios::in) immediately clears the contents of the shared memory. ) Copy and move constructors are not available. manpagesection(OVERLOADED OPERATORS) The overloaded move and copy assignment operators are not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) and the tt(enum) values tt(kB, MB), and tt(GB), defined by tt(FBB::SharedEnum__) are available. itemization( itb(void clear()) The shared memory is first locked. Next, all shared data segment are returned to the operating system, after which the shared memory segment is unlocked again. Returning from tt(clear) the shared memory The bf(FBB::SharedMemory) object is effectively re-initialized, with tt(offset) and tt(nReadable) returning 0. itb(int id() const) The ID of the shared memory segment is returned. itb(void kill()) Without locking the shared memory the bf(FBB::SharedStreambuf)'s shared memory is deleted. The bf(FBB::SharedStreambuf) object is unusable after returning from tt(kill). itb(void remove()) The shared memory is locked, and the bf(FBB::SharedStreambuf)'s shared memory is deleted. The bf(FBB::SharedStreambuf) object is unusable after returning from tt(remove). itb(void setMemory(SharedMemory &&tmp)) The anonymous temporary tt(SharedMemory) object that is passed to tt(setMemory) defines the new shared memory segment to which the bf(FBB::SharedStreambuf) object interfaces. It can also be called to reuse a bf(FBB::SharedStreambuf) object again after calling tt(kill) or tt(remove). itb(void memInfo(std::ostream &out)) Information about the tt(SharedMemory) object is inserted into the provide tt(ostream) object. The IDs of the shared segments, their sizes, the maximum number of shared memory segments, the number of bytes that can be read from the shared memory, and its actual storage capacity, etc., are displayed. The inserted information is not terminated by a final newline character. ) manpagesection(PROTECTED MEMBER FUNCTION) itb(void setOpenMode(std::ios::openmode flag)) The streambuf's tt(openmode) is changed to the settings defined by tt(flag). This member is used by, e.g., tt(SharedStream::open), to adapt the bf(FBB::SharedStreambuf)'s tt(openmode) to the flags that are passed to tt(open). ) manpagesection(EXAMPLE) See the bf(sharedstream)(3bobcat) man page. manpagefiles() em(bobcat/sharedstreambuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(chmod)(1), bf(isharedstream)(3bobcat), bf(osharedstream)(3bobcat), bf(sharedblock)(3bobcat), bf(sharedmemory)(3bobcat) bf(sharedmutex)(3bobcat), bf(sharedpos)(3bobcat), bf(sharedsegment)(3bobcat), bf(sharedstream)(3bobcat) manpagebugs() Note that by default exceptions thrown from within a bf(std::stream) object are caught by the stream object, setting its tt(ios::failbit) flag. To allow exceptions to leave a stream object, its tt(exceptions) member can be called, e.g., using: verb( myStream.exceptions(ios::failbit | ios::badbit | ios::eofbit); ) includefile(include/trailer) bobcat-3.19.01/documentation/man/datetime.yo0000644000175000017500000006516412222576535017721 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::DateTime)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Date and Time) manpagename(FBB::DateTime)(Performs Date and Time Computations) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() This class allows the programmer to manipulate date and time values. Individual time fields can be requested or modified, returning `sanitized' times (e.g., a date like march 33 or a time like 56 hours will never be returned). Times may be specified in local time or in em(Universal Time Coordinated) (tt(UTC)) values. It is also possible to add or subtract seconds or bf(struct tm) structures to or from tt(DateTime) objects. This operation keeps the current time zone (tt(UTC), local or another time zone). Conversions between time zones and tt(UTC) are also supported. The class tt(DateTime) supports various ways to initialize objects. Time may be specified in UTC, as local time or using any other offset from UTC. When an explicit time offset is requested it is specified as an tt(int) value representing the time offset in minutes, with time zones time zones West of Greenwich using negative time offsets and East of Greenwich using positive time offsets. Time zone offsets are truncated to multiples of 30 minutes and are always computed modulo 12 * 60, as no time zone has a shift exceeding the (absolute) shift of 12 * 60. Daylight saving times are in effect in many time zones. Except for the local time zone tt(DateTime) may not be able to show the correct daylight saving time correction. There are various ways to construct tt(DateTime) objects: time in seconds since the beginning of the `era' (midnight Jan 1, 1970 UTC), a tt(struct tm), or a textual time representations may be used. These values may themselves be corrected using display zone shifts. A display zone shift determines the difference between the UTC time and the local time zone to be used when displaying time or returning time fields. Sometimes a UTC zone shift may be provided correcting a provided local time to UTC. If a display zone shift is explicitly specified no additional daylight saving time (DST) zone shift is added to the display time. If the actual local time is requested (specified by the tt(TimeType) value tt(LOCALTIME)) a DST correction is automatically applied when appropriate. Members of the class tt(DateTime) should only be used if tt(operator bool()) returns tt(true). The member tt(error()) can also be used if tt(operator bool()) returns false. Handling time is complex. The bf(C) function bf(time)(2) returns the time in seconds. This time is normally represented in UTC. The function bf(gmtime)(3) when provided with tt(time())'s output returns the broken down time in a tt(struct tm). Remarkably (and confusingly), when this tt(struct tm) is then passed to the bf(mktime)(3) function the latter function does em(not) return the UTC-time in seconds, but a time that differs from the time in UTC by the current local time shift. E.g., the program verbinclude(../../datetime/driver/demos/localtime.cc) displays the current em(UTC) clock's hour setting, but reports the difference in seconds between the local time and the UTC time (e.g., the difference between CET and UTC is one hour, and the program displays 3600). To obtain the time in UTC-seconds from tt(mktime)(3) the function bf(localtime)(3) must be used to obtain the tt(struct tm) values: verbinclude(../../datetime/driver/demos/utc.cc) The above program displays the local clock's hour value, but a difference of 0 for the recomputed time in seconds. The class tt(DateTime) assumes that the tt(time()) function returns the UTC time in seconds, which is the way computers should have configured their hardware clock. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ENUMS defined in DateTime) bf(DateTime::Month)nl() This enumeration has the following values which are ordered using the default bf(C++) tt(enum) values: itemization( it() bf(JANUARY), it() bf(FEBRUARY), it() bf(MARCH), it() bf(APRIL), it() bf(MAY), it() bf(JUNE), it() bf(JULY), it() bf(AUGUST), it() bf(SEPTEMBER), it() bf(OCTOBER), it() bf(NOVEMBER), it() bf(DECEMBER). ) bf(DateTime::Relative)nl() This enumeration is used with the tt(setMonth()) member (see below). It has the following values: itemization( it() bf(THIS_WEEK), it() bf(THIS_YEAR), it() bf(LAST), it() bf(NEXT) ) bf(DateTime::TimeFields)nl() This enumeration has the following values which can be tt(bit_or)-ed when calling the member tt(setFields()): itemization( it() bf(SECONDS) it() bf(MINUTES) it() bf(HOURS) it() bf(MONTHDAY) it() bf(MONTH) it() bf(YEAR) ) bf(DateTime::TimeType)nl() This enumeration has the following values: itemization( it() bf(LOCALTIME): the time is broken down as the local time, it() bf(UTC): the time is broken down as Universal Time Coordinated. ) bf(DateTime::TriVal)nl() This enumeration has the following values, returned by the bf(dst()) member (see below): itemization( it() bf(UNKNOWN), returned when no information about the Daylight Saving Time is available, it() bf(NO), returned when Daylight Saving Time is not active, it() bf(YES), returned when Daylight Saving Time is active. ) bf(DateTime::Weekday)nl() This enumeration has the following values which are ordered using the default bf(C++) tt(enum) values: itemization( it() bf(SUNDAY), it() bf(MONDAY), it() bf(TUESDAY), it() bf(WEDNESDAY), it() bf(THURSDAY), it() bf(FRIDAY), it() bf(SATURDAY). ) manpagesection(STANDARD TEXTUAL TIME REPRESENTATIONS) tt(DateTime) objects may be initialized using textual time-representations. Also, the time represented by a tt(DateTime) object may be altered using text which can be extracted from a stream using the extraction operator. Time specifications may be formatted as follows: itemization( itt(Sun Nov 2 13:29:11 2008), as displayed by the bf(C) function tt(asctime()); itt(Sun Nov 2 13:29:11 CET 2008), as displayed by the bf(date)(1) program; itt(Sun, Nov 2 13:29:11 2008 +0100), as displayed by the tt(date -R) command (and the tt(rfc2822()) member, see below); itt(2008-11-02 13:29:11+01:00), as displayed by the tt(date --rfc-3339=seconds) command (and the tt(rfc3339()) member, see below). ) The time zone time shift specifications (+0100, +01:00) are required as they are part of the rfc specifications but are ignored for the actual local time construction as the tt(DateTime) object determines the time zone specification from the computer's current time zone setting. manpagesection(CONSTRUCTORS) itemization( itb(DateTime(TimeType type = UTC)) The default constructor, initializing the object to the current date and time. The argument specifies the way the time is displayed by the tt(DateTime) object using either (by default) time in UTC or the computer's time zone shift is used to determine the current local time. itb(DateTime(int tzShift)) This constructor initializes the object to a local time which is at UTC + tzShift (in minutes). itb(DateTime(time_t time, TimeType type)) Initializes a tt(DateTime) object with information stored in the provided tt(time_t) value (time in seconds since the beginning of the era). The specified tt(time) is considered UTC or local time, depending on the tt(type) specification. itb(DateTime(time_t time, int tzShift)) Initializes a tt(DateTime) object with information stored in the provided tt(time_t) value (time is UTC time in seconds since the beginning of the era). The tt(DateTime) object defines its time as local time UTC + tzShift (in minutes). ) The following constructors ignore the DST, day of the year, and day of the week fields of the tt(struct tm) passed to the constructors: itemization( itb(DateTime(struct tm const &tm, TimeType type = UTC)) Initializes a tt(DateTime) object with information stored in the provided bf(struct tm) value. It is assumed that the tt(tm) parameter points to a tt(struct tm) representing the broken down time in either UTC or local time. If local time is requested the the computer's time zone shift is used. The bf(struct tm) is defined as follows: verb( struct tm { int tm_sec; // seconds 0..59, or 60: leap second int tm_min; // minutes 0..59 int tm_hour; // hours 0..23 int tm_mday; // day of the month 1..31 int tm_mon; // month 0..11 int tm_year; // year since 1900 int tm_wday; // day of the week 0..6 int tm_yday; // day in the year 0..365 int tm_isdst; // daylight saving time // > 0: yes, 0: no, < 0: unknown }; ) Values outside of these ranges may sometimes be used (with various set..() members, see below) to compute a point in time in the future or in the past. E.g., by specifying 30 for the hour-setting bf(DateTime) objects a point in time in the next day will be used. itb(DateTime(struct tm const &tm, int timeShift)) Initializes a tt(DateTime) object with information stored in the provided bf(struct tm) value. It is assumed that the tt(tm) parameter points to a tt(struct tm) representing the broken down time fields in UTC. To this time shift tt(tzShift) (in minutes) is added to obtain the actually used local time. ) The final constructors convert textual time specifications formatted as described in section bf(STANDARD TEXTUAL TIME REPRESENTATIONS) (the day of the week specification is ignored by the time conversion). itemization( itb(DateTime(std::string const &timeStr, TimeType type = UTC)) Initializes a tt(DateTime) object with information stored in the provided tt(std::string) which is interpreted as time specified in UTC or as a local time in the current time zone, depending on the specified time type. itb(DateTime(std::string const &timeStr, int tzShift)) Initializes a tt(DateTime) object with a local time computed by adding a locate timezone shift (tt(tzShift)) in minutes to the UTC time specification found in tt(timeStr). ) The copy constructor is available. manpagesection(OVERLOADED OPERATORS) All class-less overloaded operators are defined in the tt(FBB) namespace, except for the overloaded insertion operator, which is defined in the tt(std) namespace. itemization( itb(std::ostream &std::operator<<(std::ostream &str, FBB::DateTime const &dt)) Inserts a standard textual representation (without the trailing newline), of the time represented in the tt(DateTime) object into the indicated tt(ostream). The time will be displayed according to the latest tt(displayZoneShift) or tt(TimeType) specification (tt(LOCALTIME) or tt(UTC)). itb(std::istream &std::operator>>(std::istream &str, FBB::DateTime &dt)) Extracts a textual date/time representation into the tt(DateTime) object using the tt(tzShift) value currently set for the tt(DateTime) object into which the time string is extracted. The tt(istream) from which the time is extracted must contain time formatted as described in section bf(STANDARD TEXTUAL TIME REPRESENTATIONS). As documented in that section, time shift and time zone specifications (+0100, +01:00, CET) are ignored and may be omitted. They are ignored when specified. The object will merely interpret the date/time specification as a specification in the object's currently active time zone. If the time could not be determined from a textual string representing the time (cf. section bf(CONSTRUCTORS)) then tt(errno()) returns 0, tt(operator bool()) returns tt(false), and the time stored in the object remains unchanged. ) The following overloaded operators modify the time as stored in UTC seconds within objects. Note that the time as displayed by the object will be corrected for any display zone shift that may have been defined for those objects. itemization( itb(DateTime const operator+(DateTime const &left, time_t seconds)) Returns a copy of tt(left) to which tt(seconds) have been added. itb(DateTime const operator+(DateTime const &left, struct tm const &fields)) Returns a copy of tt(left) displaying tt(left)'s time to which the tt(tm_sec, tm_min, tm_hour, tm_mday, tm_mon) and tt(tm_year) fields of tt(fields) have been added. itb(DateTime operator+=(time_t seconds)) Adds the number of seconds to the tt(DateTime) object. itb(DateTime &operator+=(struct tm const &fields)) Adds the tt(tm_sec, tm_min, tm_hour, tm_mday, tm_mon) and tt(tm_year) fields of tt(fields)to the current object's display time. itb(DateTime const operator-(DateTime const &left, time_t seconds)) Returns a copy of tt(left) from which time tt(seconds) have been subtracted. itb(DateTime const operator-(DateTime const &left, struct tm const &fields)) Returns a copy of tt(left) displaying tt(left)'s time from which the tt(tm_sec, tm_min, tm_hour, tm_mday, tm_mon) and tt(tm_year) fields of tt(fields) have been subtracted. itb(DateTime operator-=(time_t seconds)) Subtracts the number of seconds from the time stored in the tt(DateTime) object. itb(DateTime &operator-=(struct tm const &fields)) Subtracts the tt(tm_sec, tm_min, tm_hour, tm_mday, tm_mon) and tt(tm_year) fields of tt(fields) from the current object's display time. E.g., the following code fragment will display midnight, January 1, 1970: verbinclude(../../datetime/driver/demos/erabody.cc) ) The following overloaded operators can be used to compare the UTC time as represented by tt(DateTime) objects. Note that these comparisons are independent of any display zone shift that may have been defined for the objects. itemization( itb(bool operator==(DateTime const &left, DateTime const &right)) Returns tt(true) if the current tt(DateTime) object represents the same UTC time as the time represented by tt(left, DateTime const &right). itb(bool operator!=(DateTime const &left, DateTime const &right)) Returns tt(true) if the current tt(DateTime) object represents a different UTC time as the time represented by tt(other). itb(bool operator<(DateTime const &left, DateTime const &right)) Returns tt(true) if the current tt(DateTime) object represents an earlier UTC time than the UTC time represented by tt(other). itb(bool operator<=(DateTime const &left, DateTime const &right)) Returns tt(true) if the current tt(DateTime) object represents an earlier or equal UTC time than the UTC time represented by tt(other). itb(bool operator>(DateTime const &left, DateTime const &right)) Returns tt(true) if the current tt(DateTime) object represents a later UTC time than the UTC time represented by tt(other). itb(bool operator>=(DateTime const &left, DateTime const &right)) Returns tt(true) if the current tt(DateTime) object represents an equal or later UTC time than the UTC time represented by tt(other). ) Additional overloaded operators: itemization( itb(operator bool() const) Returns bf(true) if the time decomposition could be performed without error. tt(DateTime) object use bf(localtime_r)(3) or bf(gmtime_r)(3) functions to break down the tt(time_t) values into elements. If the time could not be broken down, the bf(error()) member returns the error number (tt(errno)) associated with the error. When the time could not be determined from a textual string representing the time (cf. section bf(CONSTRUCTORS)) then tt(errno()) returns 0 and tt(operator bool()) returns tt(false).nl() Except for the member tt(error()) the members of the class tt(DateTime) will not return meaningfull values if bf(operator bool()) returns tt(false). itb(DateTime &operator=(DateTime const &other)) The overloaded asignment operator is available. ) manpagesection(MEMBER FUNCTIONS) All members returning a time-element do so according to the latest time-representation (i.e., tt(UTC), tt(LOCALTIME), or using an explicitly set display zone shift value). All members returning numerical values use 0 as their smallest return value, except for the bf(...Nr()) members, which start at 1. itemization( itb(int displayZoneShift() const) Returns the object's current display zone shift value in minutes. itb(DayTime::TriVal dst() const) Returns an indication of an active Daylight Saving Time (DST) state for the (local) time represented in the tt(DateTime) object. When DST is active, the local time is one hour later as compared to the situation where DST is not active. itb(size_t error() const) Returns the tt(errno) value after the tt(DateTime) object. construction. It can be interpreted by, e.g., bf(FBB::Exception). itb(size_t hours() const) Returns the number of hours of the time stored in a tt(DateTime) object (0-23). itb(DateTime localTime() const) Returns a copy of the tt(DateTime) object representing its local time. If the object does not define a local time or display zone shift the returned object merely copies the orginal object's UTC time. itb(DateTime localTime(int displayZoneShift) const) Returns a copy of the tt(DateTime) object representing its time using the display zone shift provided by the member's argument. itb(size_t minutes() const) Returns the number of minutes of the time stored in a tt(DateTime) object (0-59). itb(Month month() const) Returns the tt(Month) value of the time stored in a tt(DateTime) object. itb(size_t monthDayNr() const) Returns the number of the day in the month of the time stored in a tt(DateTime) object (1-31). itb(string rfc2822() const) Returns the date displayed according to the format specified in RFC 2822. This format is used, e.g., by the tt(date -R) command (cf. bf(date)(1)). For example: verb( Mon, 17 Dec 2007 13:49:10 +0100 ) itb(string rfc3339() const) Returns the date displayed according to the format specified in RFC 3339. This format is used, e.g., by the tt(date --rfc-3339=seconds) command (cf. bf(date)(1)). For example: verb( 2008-11-02 13:29:11+01:00 ) itb(size_t seconds() const) Returns the number of seconds of the time stored in a tt(DateTime) object (0-59, but 60 and 61 may occur due to possible leap seconds). itb(bool setDay(int days)) Reassigns the number of days of the current month set in the tt(DateTime) object. Non positive values are allowed to compute time in an earlier month. The object date is revalidated so that its tt(days()) member returns a value fitting the object's month. If the assignment resulted in a new (valid) time tt(true) is returned. Otherwise tt(false) is returned. itb(bool setFields(struct tm const &timeStruct, int fields)) Reassigns the time represented by the tt(DateTime) object to the time in which the fields specified by a tt(bit_or) combination of tt(TimeField) values will be given the values specified in tt(timeStruct). All other fields in tt(timeStruct) will be ignored and will be kept at their internal values. The values will be normalized, though. E.g., if the current month day number is 31 and month June is requested then the resulting month will be tt(July) and the day number will be 1. The tt(timeStruct) fields are expected as values in the time zone used by the tt(DateTime) object. If the assignment resulted in a new (valid) time tt(true) is returned. Otherwise tt(false) is returned. itb(bool setHours(int hours)) Reassigns the number of hours set in the tt(DateTime) object. Negative values are allowed to compute time in a previous day. The object date is revalidated so that its tt(hours()) member returns a value between 0 and 23. If the assignment resulted in a new (valid) time tt(true) is returned. Otherwise tt(false) is returned. itb(bool setMinutes(int minutes)) Reassigns the number of minutes set in the tt(DateTime) object. Negative values are allowed to compute time in a previous hour. The object date is revalidated so that its tt(minutes()) member returns a value between 0 and 59. If the assignment resulted in a new (valid) time tt(true) is returned. Otherwise tt(false) is returned. itb(bool setMonth(DateTime::Month month, DateTime::Relative where = THIS_YEAR)) Reassigns the month set in the tt(DateTime) object. The object date is revalidated so that its tt(month()) member returns a value between tt(JANUARY) and tt(DECEMBER). By default the month will be set in the current year. tt(DateTime::LAST) may be specified to ensure that the requested month will be before the current month (e.g., the current month: tt(JUNE), requesting tt(AUGUST, LAST) will decrement the object's year, but tt(MAY, LAST) won't). Analogously, tt(DateTime::NEXT) may be specified to ensure that the requested month will be following the current month. If another value for tt(where) is specified an bf(Exception) exception is thrown. If the assignment resulted in a new (valid) time tt(true) is returned. Otherwise tt(false) is returned. Caveat: When setting the month the month may inadvertently be set to the next month. This happens when the current day number exceeds the number of days in the target month. Example: assume it is December 31st and the intent is to change the date to June 21st. The first example sets the date to bf(July) 21st since `June 31st' is converted to `July 1st'. The second example sets the date to June 21st, as intended. verb( DateTime dt; // assume set at December 31 dt.setMonth(DateTime::JUNE); // becomes JULY dt.setDay(21); // Now July 21st DateTime dt; // assume set at December 31 dt.setDay(21); // Now December 21st dt.setMonth(DateTime::JUNE); // OK: June 21st ) itb(bool setMonth(int month)) Reassigns the month set in the tt(DateTime) object. Negative values are allowed to compute time in a previous year. The object date is revalidated so that its tt(month()) member returns a value between tt(JANUARY) and tt(DECEMBER). If the assignment resulted in a new (valid) time tt(true) is returned. Otherwise tt(false) is returned. itb(bool setSeconds(int seconds)) Reassigns the number of seconds set in the tt(DateTime) object. Negative values are allowed to compute time in a previous minute. The object date is revalidated so that its tt(seconds()) member returns a value between 0 and 59. If the assignment resulted in a new (valid) time tt(true) is returned. Otherwise tt(false) is returned. itb(bool setTime(time_t time)) Reassigns the number of seconds set in the tt(DateTime) object. The object date is revalidated. Time value 0 represents Jan, 1, 1970, 0:00:00 hours. If the assignment resulted in a new (valid) time tt(true) is returned. Otherwise tt(false) is returned. itb(void setValid()) Resets the object's internal state to valid. This member can be used following a failed action that did not modify the (valid) time stored by the object. itb(bool setWeekday(Weekday day, Relative where = NEXT)) Reassigns the number of seconds set in the tt(DateTime) object based on reassignment of the day in the week (at most 7 days from now, weeks starting at Sunday and ending at Saturday). By default the day will be in the future. By specifying tt(LAST) for tt(where) the day will be in the past. It is also possible to specify tt(where) as tt(THIS_WEEK) in which case the day will be computed in the current week. If another value for tt(where) is specified an bf(Exception) exception is thrown. If the current weekday is specified with tt(where) equal to either tt(NEXT) or tt(LAST) the time will be set to either one week ahead or one week in the past. The object date is revalidated. Time value 0 represents Jan, 1, 1970, 0:00:00 hours. If the assignment resulted in a new (valid) time tt(true) is returned. Otherwise tt(false) is returned. itb(bool setYear(size_t year)) Reassigns the year set in the tt(DateTime) object. The date is revalidated so that its tt(year()) member returns a value of at least 1970. If the assignment resulted in a new (valid) time tt(true) is returned. Otherwise tt(false) is returned. itb(time_t time() const) Returns the (UTC) tt(time_t) value (in seconds) stored in the tt(DateTime) object. itb(struct tm const *timeStruct() const) Returns a pointer to the objects latest tt(struct tm) values, representing the time as displayed by, e.g., the insertion operator. itb(DateTime to(DateTime::TimeType type) const) Returns a copy of the tt(DateTime) object representing its time in tt(UTC) if tt(DateTime::UTC) was specified, and in local time if tt(DateTime::LOCALTIME) was specified. itb(DateTime utc() const) Returns a copy of the tt(DateTime) object representing its time in tt(UTC). itb(bool valid() const) Returns tt(true) if no errors were detected during the object's construction (same semantics as tt(operator bool())). itb(Weekday weekday() const) Returns the tt(Weekday) value of the time stored in a tt(DateTime) object. itb(size_t year() const) Returns the year element of the time stored in a tt(DateTime) object. itb(size_t yearDay() const) Returns the day within the year of the time stored in a tt(DateTime) object. January 1 is returned as 0. itb(size_t yearDayNr() const) Returns the day within the year of the time stored in a tt(DateTime) object. January 1 is returned as 1. ) Whenever a tt(set...()) member is used in such a way that the resulting date would be invalid the original tt(DateTime) object's value is unaltered. manpagesection(EXAMPLE) An extensive example illustrating the use of all of tt(DateTime)'s members is provided in the file tt(bobcat/datetime/driver/driver.cc) found in the source archive. manpagefiles() em(bobcat/datetime) defines the class interface. manpageseealso() bf(bobcat)(7), bf(Exception)(3bobcat), bf(asctime_r)(3), bf(gmtime_r)(3), bf(localtime_r)(3), bf(time)(2), bf(mktime)(3), manpagebugs() The class tt(DateTime) assumes that bf(time)(2) returns the time in UTC.nl() English is used / expected when specifying named date components. includefile(include/trailer) bobcat-3.19.01/documentation/man/selector.yo0000644000175000017500000001433512222576535017737 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Selector)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Timed Delays, Multiple File I/O) manpagename(FBB::Selector)(Timed delays, Alarms and Multiple File I/O.) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::Selector) objects are wrappers around the bf(select)(2) system calls and allow timed delays, alarm functionality and/or multiple file I/O. It requires the use of em(file descriptors), which are not an official part of bf(C++). However, most operating systems offer em(file descriptors). Sockets are well-known file descriptors. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) itemization( itb(Selector()) This constructor initializes the object. ) The copy constructor is available. manpagesection(MEMBER FUNCTIONS) itemization( itb(void addExceptFd(int fd)) Adds a filedescriptor to the set of file descriptors that are monitored for exceptions (note these are not bf(C++) exceptions. See tt(man 2 select) for details). itb(void addReadFd(int fd)) Adds a filedescriptor to the set of file descriptors that are monitored for reading. itb(void addWriteFd(int fd)) Adds a filedescriptor to the set of file descriptors that are monitored for writing. itb(int exceptFd()) Returns -1 of no more file descriptors are available in the em(exception) category. Otherwise the next available file descriptor in the em(exception) category is returned. Returning from tt(wait), this function can be called repeatedly until -1 is returned, servicing each available filedescriptor in turn. itb(void noAlarm()) This member prevents any timeout-alarm from occurring. itb(int nReady()) Returns the number of available file descriptors. 0 is returned at a timeout, -1: is returned when tt(select)(2) itself failed. itb(int readFd()) Returns -1 of no more file descriptors are available for reading. Otherwise the next available file descriptor for reading is returned. Returning from tt(wait), this function can be called repeatedly until -1 is returned, servicing each available filedescriptor in turn. Note that the file whose file descriptor is returned by tt(readFd) may also be at its end-of-file position. The file is `ready for reading', but no characters will be returned when trying to read from it due to its end-of-file status. In that case the file descriptor is probably best removed from the set of active file descriptors. itb(void rmExceptFd(int fd)) Removes a filedescriptor from the set of file descriptors that are monitored for exceptions (note these are not bf(C++) exceptions. See tt(man 2 select) for details). itb(void rmReadFd(int fd)) Removes a filedescriptor from the set of file descriptors that are monitored for reading. itb(void rmWriteFd(int fd)) Removes a filedescriptor from the set of file descriptors that are monitored for writing. itb(void setAlarm(int sec, int usec = 0)) This member sets the alarm at the indicated seconds and micro-seconds. If no action occurred on one of the monitored file descriptions following the indicated amount of time, tt(wait) will return with tt(nReady) returning 0. The requested alarm time (tt(sec + usec / 1e+6)) may not be negative and may not exceed tt(std::numeric_limits::max()) or an tt(FBB::Exception) exception (see tt(setAlarm)) will be thrown. A 0 alarm time specification results in tt(wait) returning immediately. To switch off the alarm time use tt(noAlarm). itb(int wait()) This member should be called to wait for activities on the installed file descriptors or timeout-period. The members tt(exceptFd, nReady, readFd) and tt(writeFd) show their defined behaviors only after tt(wait) has returned. It throws an tt(FBB::Exception) exception when bf(select)(2) fails, which may very well indicate the end of any available input. Otherwise it returns the number of available file descriptors. Note that tt(wait) may also return with an input file descriptor returned by tt(readFd) of a file at its end-of-file position. The file is `ready for reading', but no characters will be returned when trying to read from it due to its end-of-file status. itb(int writeFd()) Returns -1 of no more file descriptors are available for writing. Otherwise the next available file descriptor for writing is returned. Returning from tt(wait), this function can be called repeatedly until -1 is returned, servicing each available filedescriptor in turn. ) manpagesection(EXAMPLE) verb( #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { Selector selector; selector.setAlarm(5); // every 5 secs: alarm fires selector.addReadFd(STDIN_FILENO); // look also at cin try { while (true) { if (!selector.wait()) // 0: alarm fires cout << "Are you still there?" << endl; else { string s; if (!getline(cin, s) || !s.length()) return 0; cout << "Thank you for: " << s << endl; } } } catch (Exception const &e) { cout << e.what() << endl; } return 0; } ) manpagefiles() em(bobcat/selector) - defines the class interface manpageseealso() bf(bobcat)(7), bf(select)(2) manpagebugs() Not so much a bug as something to be aware of: When removing input file descriptors of files at their end-of-file positions the set of active file descriptors monitored by tt(wait) may decay to an empty set. If tt(wait) is thereupon called it will wait forever since there are no more file descriptors to monitor. The monitoring process should check for this empty-set situation before calling tt(wait). Facilities to prevent tt(wait) from waiting indefinitely in this situation will be added to tt(Selector) in a future Bobcat release. includefile(include/trailer) bobcat-3.19.01/documentation/man/iostream.yo0000644000175000017500000000606012222576535017736 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::IOStream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (std::istream and std::ostream) manpagename(FBB::IOStream)(Combines std::istream and std::ostream features) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() This class combines the features of the bf(std::istream) and bf(std::ostream) classes. The bf(std::istream) and bf(std::ostream) may be physically different streams. bf(FBB:IOStream) objects may, e.g., be associated with streams wrapped around em(pipes) (see, e.g., bf(FBB::IfdStream) and bf(FBB::OFdStream)), to construct bi-directional pipes. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::IOStreambuf) (private inheritance),nl() bf(std::istream),nl() bf(std::ostream) manpagesection(CONSTRUCTORS) itemization( itb(IOStream()) The default constructor constructs an empty bf(FBB::IOStream) objects. It should not be used before its tt(open) member (see below) was called. itb(IOStream(std::istream &in, std::ostream &out)) This constructor associates the bf(IOStream) object with a tt(std::istream) and a tt(std::ostream). All output operations will be passed on to the tt(std::ostream), all input operations to the tt(std::istream). The streams passed to tt(IOStream) should outlive the bf(IOStream) object. This constructor performs the actions of the default constructor and then calls the tt(IOStream::open) member ) De copy constructor is available as well. manpagesection(MEMBER FUNCTIONS) All members of tt(std::istream) and tt(std::ostream) are available, as bf(FBB::IOStream) inherits from these classes. Furthermore, when switching between tt(std::istream) and tt(std::ostream) operations, no intermediate tt(seekg()) or tt(seekp()) operation will normally be required, since the base classes will normally be associated with physically different streams. itemization( itb(void open(std::istream &in, std::ostream &out)) This member (re)associates the bf(IOStream) object with a tt(std::istream) and a tt(std::ostream). All output operations will be passed on to the tt(std::ostream), all input operations to the tt(std::istream). The streams passed to tt(IOStream()) should outlive the bf(IOStream) object. If this member is called for an bf(IOStream) object already associated with an tt(std::ostream) object, the already associated tt(std::ostream) object is flushed before setting up the new association. itb(void clear()) This member clears the error states of the associated tt(std::istream) and tt(std::ostream) objects. ) manpagesection(EXAMPLE) See the example provided with bf(process)(3bobcat). manpagefiles() em(bobcat/iostream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ifdstream)(3bobcat), bf(iostreambuf)(3bobcat), bf(ofdstream)(3bobcat), bf(process)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/digestbuf.yo0000644000175000017500000001101112222576535020057 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Digestbuf)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Compute Message Digests) manpagename(FBB::Digestbuf) (Computes Message Digests from information inserted into a std::ostream) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::Digestbuf) objects are bf(std::streambuf) objects that can be used to initialize tt(std::ostream) objects with. All information inserted into such a tt(std::ostream) is used to compute a message digest from. All the message digests defined by the OpenSSL library that can be selected by name may be used in combination with tt(DigestBuf) objects. The following message digest algorithms are currently supported: mull, md2, md5, sha, sha1, sha224, sha256, sha384, sha512, dss, dss1, ecdsa, mdc2, ripemd160. These very names are the ones to use to select the particular digest algorithms for the class's constructor, below. It is quite possible that future releases of the openssl library will support additional message digest algorithms. The header file tt(openssl/evp.h) lists all available digest algorithms (in that file look for tt(EVP_MD *EVP_): a message digest algorithm immediately follows the 2nd underscore. E.g., tt(const EVP_MD *EVP_md4(void)) which refers to the md4 message digest algorithm). includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(CONSTRUCTORS) itemization( itb(Digestbuf(char const *type, size_t bufsize = 1024)) This constructor initializes the streambuf, setting it up for the message digest algorithm specified with tt(type). The message digest algorithms specified in the bf(DESCRIPTION) section may be used here. E.g., to use the sha256 algorithm specify tt("sha256"). The tt(bufsize) argument specifies the internal buffer used by tt(Digestbuf) to store incoming characters temporarily. The provided default argument should be OK in all normal cases. ) There is no copy constructor. manpagesection(OVERLOADED OPERATOR) itemization( itb(std::ostream &operator<<(std::ostream &out, DigestBuf const &digestbuf)) The insertion operator is a free function defined in the namespace tt(FBB). It inserts a hash value as a series of hexadecimally displayed values into the provided tt(ostream). See the example below for an illustration. ) The overloaded assignment operator is not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::Digestbuf) inherits from this class. Some of the bf(std::streambuf)'s member are overridden or are hidden by tt(Digestbuf). In normal situations these inherited members will not be used by programs using tt(DigestBuf) objects. itemization( itb(void close()) This member finishes the computation of the message digest computation. It is needed as the tt(DigestBuf) object has no external means for deciding whether all information to compute the digest for has yet been received or not. The general approach to follow when computing a message digest is therefore: verb( create a DigestBuf object use it to create a std::ostream object insert information into the ostream object call the DigestBuf object's close() member obtain/process the hash value from the DigestBuf object. ) itb(std::string const &hash() const) This member returns the hash value computed by the tt(DigestBuf) object. Its value is only defined after having called tt(close()). The hash value is returned in a tt(std::string) object. This string's tt(length()) member contains the number of characters used by the hash value, and its tt(data()) member refers to the hash value's characters. Note that a hash value's character value may be 0 (not to be confused with tt('0')). itb(void open()) This member reinitializes the message digest computation. One a message digest has been computed for, say a stream tt(streamA) this member can be called after which the digest for a stream tt(streamB) can be computed using the same tt(DigestBuf) object. ) manpagesection(EXAMPLE) verbinclude(../../digestbuf/driver/driver.cc) manpagefiles() em(bobcat/digestbuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(hmacbuf)(3bobcat), bf(std::streambuf) manpagebugs() None reported includefile(include/trailer) bobcat-3.19.01/documentation/man/symcryptciphers0000644000175000017500000001016112222576535020732 0ustar frankfrankCOMMENT( method type keysize blocksize identifier) def(ROW)(5)(row(cell(ARG1)cell(ARG2)cell(ARG3)cell(ARG4)cell("ARG5"))) The following table presents an overview of methods that are currently available. Methods for which the block size is specified as N.A. are stream ciphers; other methods are block ciphers: table(5)(lllll)( rowline() row(cell(method)cell(keysize)cell(blocksize)cell(mode)cell(identifier)) row(cell()cell((bytes))cell((bytes))) rowline() ROW(AES) (16) (8)(CBC)(aes-128-cbc) ROW() ( ) ( )(EBC)(aes-128-ecb) ROW() ( ) ( )(CFB)(aes-128-cfb) ROW() ( ) ( )(OFB)(aes-128-ofb) ROW() (24) (24)(CBC)(aes-192-cbc) ROW() ( ) ( )(EBC)(aes-192-ecb) ROW() ( ) ( )(CFB)(aes-192-cfb) ROW() ( ) ( )(OFB)(aes-192-ofb) ROW() (32) (32)(CBC)(aes-256-cbc) ROW() ( ) ( )(EBC)(aes-256-ecb) ROW() ( ) ( )(CFB)(aes-256-cfb) ROW() ( ) ( )(OFB)(aes-256-ofb) rowline() ROW(BLOWFISH)(16) (8)(CBC)(bf-cbc) ROW() ( ) ( )(EBC)(bf-ecb) ROW() ( ) ( )(CFB)(bf-cfb) ROW() ( ) ( )(OFB)(bf-ofb) row(setmanalign(lssss)cell(max key length is 56 bytes, 16 generally used)) rowline() ROW(CAMELLIA) (16) (16)(CBC)(camellia-128-cbc) ROW() ( ) ( )(EBC) (camellia-128-ecb) ROW() ( ) ( )(CFB) (camellia-128-cfb) ROW() ( ) ( )(OFB) (camellia-128-ofb) ROW() (24) ()(CBC) (camellia-192-cbc) ROW() ( ) ( )(EBC) (camellia-192-ecb) ROW() ( ) ( )(CFB) (camellia-192-cfb) ROW() ( ) ( )(OFB) (camellia-192-ofb) ROW() (32) ()(CBC) (camellia-256-cbc) ROW() ( ) ( )(EBC) (camellia-256-ecb) ROW() ( ) ( )(CFB) (camellia-256-cfb) ROW() ( ) ( )(OFB) (camellia-256-ofb) rowline() ROW(CAST)(16) (8)(CBC)(cast-cbc) ROW() ( ) ( )(EBC)(cast-ecb) ROW() ( ) ( )(CFB)(cast-cfb) ROW() ( ) ( )(OFB)(cast-ofb) row(setmanalign(lssss) cell(min key length is 5 bytes, max is shown)) rowline() ROW(DES)(8)(8)(CBC)(des-cbc) ROW() ( )( )(EBC)(des-ebc) ROW() ( )( )(CFB)(des-cfb) ROW() ( )( )(OFB)(des-ofb) rowline() ROW(DESX)(8)(8)(CBC)(desx-cbc) rowline() ROW(3DES)(16)(8)(CBC)(des-ede-cbc) ROW() ( ) ( )(EBC)(des-ede) ROW() ( ) ( )(CFB)(des-ede-cfb) ROW() ( ) ( )(OFB)(des-ede-ofb) rowline() ROW(3DES)(24)(8)(CBC)(des-ede3-cbc) ROW() ( ) ( )(EBC)(des-ede3) ROW() ( ) ( )(CFB)(des-ede3-cfb) ROW() ( ) ( )(OFB)(des-ede3-ofb) row(setmanalign(lssss) cell(Key bytes 9-16 define the 2nd key, bytes 17-24)) row(setmanalign(lssss)cell(define the 3rd key)) rowline() ROW(RC2) (16)(8)(CBC)(rc2-cbc) ROW() ( ) ( )(EBC)(rc2-ecb) ROW() ( ) ( )(CFB)(rc2-cfb) ROW() ( ) ( )(OFB)(rc2-ofb) row(setmanalign(lssss)\ cell(Key length variable, max. 128 bytes, default length is shown)) rowline() ROW(RC2-40)(5)(8)()(rc2-40-cbc) row(setmanalign(lssss)cell(obsolete: avoid)) rowline() ROW(RC2-64)(8)(8)()(rc2-64-cbc) row(setmanalign(lssss)cell(obsolete: avoid)) rowline() ROW(RC4)(16)(N.A.)()(rc4) row(setmanalign(lssss)\ cell(Key length is variable, max. 256 bytes. default length is shown)) row(setmanalign(lssss) cell(Encrypt again to decrypt. Don't use tt(DecryptBuf))) rowline() ROW(RC4-40)(5)(N.A.)()(rc4-40) row(setmanalign(lssss)cell(obsolete: avoid)) rowline() ROW(RC5) (16)(8) (CBC)(rc5-cbc) ROW() ( ) ( ) (EBC)(rc5-ecb) ROW() ( ) ( ) (CFB)(rc5-cfb) ROW() ( ) ( ) (OFB)(rc5-ofb) row(setmanalign(lssss) cell(Key length variable, max. 256 bytes, rounds 8, 12 or 16,)) row(setmanalign(lssss) cell(default # rounds is 12)) rowline() ) The RC4 stream cipher is subject to a well-known attack (cf. lurl(http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Mantin1.zip)) unless the initial 256 bytes produced by the cipher are discarded. bobcat-3.19.01/documentation/man/decryptbuf.yo0000644000175000017500000001363212222576535020265 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::DecryptBuf)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Decrypt information) manpagename(FBB::DecryptBuf) (Decrypts information using various methods into a std::ostream) manpagesynopsis() bf(#include )nl() Linking option: tt( -lbobcat) manpagedescription() bf(FBB::DecryptBuf) objects are bf(std::streambuf) objects that can be used to initialize tt(std::ostream) objects with. All information inserted into such a tt(std::ostream) is decrypted and written into a tt(std::ostream) that is given as argument to tt(DecryptBuf)'s constructor. All encryption methods defined by the OpenSSL library that can be selected by name may be used in combination with tt(DecryptBuf) objects. Most likely the information will have been encrypted using an tt(EncryptBuf) object, selecting a particular encryption method. The encryption method used when encrypting information should also be specified when constructing a tt(DecryptBuf) object. Likewise, the constructor expects a em(key) and em(initialization vector). The key and initialization vector that was passed to the tt(EncryptBuf) object must be passed to tt(DecryptBuf)'s constructor as well. includefile(blockciphers) includefile(symcryptciphers) includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(CONSTRUCTOR/DESTRUCTOR) itemization( itb(DecryptBuf(std::ostream &outStream, char const *type, std::string const &key, std::string const &iv, size_t bufsize = 1024)) This constructor initializes the tt(DecryptBuf) object preparing it for the message decrypt algorithm specified with tt(type). The decryption algorithms that can be used are listed in the table found in the bf(EncryptBuf)(3bobcat) manual page. As an example: to use the AES method on 192 bit keys and blocks in CBC mode specify tt("aes-192-cbc"). The tt(key) parameter refers to the key to be used, the tt(iv) parameter refers to the initialization vector to use. The tt(iv)'s length cannot be zero. When using ECB modes no initialization vector is used. In those cases any non-empty initialization vector may be provided. The constructor throws an tt(FBB::Exception) exception if an unknown encryption method was specified. The constructor's first parameter refers to the tt(std::ostream) to receive the decrypted information. The tt(bufsize) argument specifies the size in bytes of the internal buffer used by tt(DecryptBuf) to store incoming characters temporarily. The provided default argument should be OK in all normal cases. itb(~DecryptBuf()) The destructor calls the tt(done()) member (see below), prevending any exception that function might throw from leaving the destructor. In this case only a non thread-safe way to determine whether the decryption was successfully completed is available through the static member function tt(lastOK()) (see below). ) There is no copy constructor, nor move constructor (as tt(std::streambuf) doesn't support either). manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::DecryptBuf) inherits from this class. Some of the bf(std::streambuf)'s member are overridden or are hidden by tt(DecryptBuf). In normal situations these inherited members will not be used by programs using tt(DecryptBuf) objects. itemization( itb(void done()) This member can be called to indicate that all information to be decrypted has been received. It throws an tt(FBB::Exception) exception if decryption fails (resulting from providing the tt(DecryptBuf) object with incorrect (usually improperly padded) input). If not explicitly called it is called by tt(DecryptBuf)'s destructor, preventing its exception from leaving the destructor. itb(void setIv(std::string const &iv)) This member can be used to specify the initialization vector to use after construction time but before any data has been decrypted. When called after decryption has started or when specifying an empty intialization vector an tt(FBB::Exception) exception will be thrown. When using ECB modes no initialization vector is used. In those cases any non-empty initialization vector may be provided. itb(bool setRounds(size_t nRounds)) This member can only be used with the RC5 decryption method to set the number of rounds of the algorithm to 8, 12 or 16. When the number of rounds were updated successfully the member returns tt(true). It returns tt(false) in other cases (e.g., called for other decryption methods than RC5 or the requested number of rounds differ from 8, 12 or 16). ) manpagesection(STATIC MEMBER) itemization( itb(bool lastOK()) This member is a non thread-safe way to determine whether the decryption has succeeded when the tt(DecryptBuf) object's tt(done) member has not been called and the object has been destroyed. In that case the object's destructor will call tt(done) to complete the decryption. The member tt(lastOK) returns tt(true) if the tt(DecryptBuf) object destroyed last could complete its decryption successfully and returns tt(false) otherwise. ) manpagesection(PROTECTED MEMBER) itemization( itb(EVP_CIPHER_CTX *cipherCtx()) Classes derived from tt(DecryptBuf) may use this member to gain direct access to the tt(EVP_CIPHER_CTX) pointer used by the tt(DecryptBuf) object. This pointer is a pointer to an opaque structure used by many OpenSSL functions to set or query parameters of an decryption method. ) manpagesection(EXAMPLE) verbinclude(../../decryptbuf/driver/driver.cc) manpagefiles() em(bobcat/decryptbuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(encryptbuf)(3bobcat), bf(std::streambuf) manpagebugs() None reported includefile(include/trailer) bobcat-3.19.01/documentation/man/ifdstreambuf.yo0000644000175000017500000001224312222576535020566 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::IFdStreambuf)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (File Descriptor Input Stream Buffer) manpagename(FBB::IFdStreambuf) (Input stream buffer initialized by a file descriptor) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::IFdStreambuf) objects may be used as a bf(std::streambuf) of tt(std::istream) objects to allow extractions from a file descriptor. File descriptors are not defined within the context of bf(C++), but they can be used on operating systems that support the concept. Realize that using file descriptors introduces operating system dependencies. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(ENUMERATION) The public enumeration bf(Mode) defined in the class bf(FBB::IFdStreamBuf) has the following values: itemization( it() bf(CLOSE_FD), indicating that the file descriptor used by the object must be closed; it() bf(KEEP_FD) (the default) indicating that the file descriptor used by the object must not be closed. ) manpagesection(CONSTRUCTORS) itemization( itb(Ifdstreambuf()) This constructor initializes the streambuf, without associating it to a file descriptor, and without using buffering. The member bf(open()) can be used subsequently to associate the object with a file descriptor and optionally a buffer size. When the object is destroyed or if the mode-less overloaded version of the bf(open) member is called, the file descriptor will not be closed. itb(Ifdstreambuf(Mode mode)) This constructor initializes the streambuf, without associating it to a file descriptor, and without using buffering. The member bf(open()) can be used subsequently to associate the object with a file descriptor and optionally a buffer size. When the object is destroyed or if the mode-less overloaded version of the bf(open) member is called, the bf(Mode) argument determines whether the file descriptor will be closed or will remain open. itb(IFdStreambuf(int fd, size_t n = 1)) This constructor initializes the streambuf, associating it to file descriptor tt(fd), and an optional unget buffer size (by default having size 1). When the object is destroyed or if the mode-less overloaded version of the bf(open) member is called, the file descriptor will not be closed. itb(IFdStreambuf(int fd, Mode mode, size_t n = 1)) This constructor initializes the streambuf, associating it to file descriptor tt(fd), and an optional unget buffer size (by default having size 1). When the object is destroyed or if the mode-less overloaded version of the bf(open) member is called, the bf(Mode) argument determines whether the file descriptor will be closed or will remain open. ) There is no copy constructor. manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::IFdStreambuf) inherits from this class. Some of the bf(std::streambuf)'s member are overridden by bf(FBB::IFdStreambuf), see below. itemization( itb(void close()) The file descriptor used by the tt(IFdStreambuf) is closed, irrespective of the tt(Mode) that was specified when the tt(IFdStreambuf) object was constructed. Following tt(close) the tt(IFdStreambuf) object can no longer be used until one of its tt(open) members has been called. itb(int fd() const) The file descriptor used by the tt(IFdStreambuf) object is returned. If the tt(OFdStreambuf) is not associated with a file descriptor -1 is returned. itb(void open(int xfd, size_t n = 1)) The streambuf is (re)initialized, using file descriptor tt(fd), and an optional unget buffer size (by default having size 1). When called repeatedly, the bf(Mode) specification used whem the object was constructed determines whether the file descriptor will be closed or will remain open. itb(void open(int xfd, Mode mode, size_t n = 1)) The streambuf is (re)initialized, using file descriptor tt(fd), a file descriptor closing parameter and an optional unget buffer size (by default having size 1). Depending on the bf(Mode) argument the object's currently used file descriptor will be closed or will remain open when the tt(IFdStreambuf) object is destroyed. ) Note that there is no overloaded assignment operator available for this class. manpagesection(EXAMPLE) To do manpagefiles() em(bobcat/ifdstreambuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ifdstream)(3bobcat), bf(ofdstreambuf)(3bobcat), bf(std::streambuf) manpagebugs() The member tt(xsgetn(char *dest, std::streamsize n)) will set tt(istream::good()) to tt(false) when fewer bytes than tt(n) were read using tt(istream::read()). Also see tt(xsgetn)'s description. Note that by default the provided file descriptors remain open. The complementary class bf(ofdstreambuf)(3bobcat) em(closes) the file descriptor by default. This inconsistency was deliberately accepted to keep the classes interfaces backward compatible. includefile(include/trailer) bobcat-3.19.01/documentation/man/cmdfinderbase.yo0000644000175000017500000000146412222576535020704 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::CmdFinderBase)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz)(Base class for CmdFinder) manpagename(FBB::CmdFinderBase) (Base class for the class CmdFinder) manpagesynopsis() see the bf(CmdFinder) manpage manpagedescription() This class is a base class for the class bf(CmdFinder). All its accessible members and features are described in the bf(CmdFinder) manpage. This class supports move and copy construction and assignment operations. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagefiles() See the bf(CmdFinder) manpage manpageseealso() bf(bobcat)(7), bf(cmdfinder)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/blockciphers0000644000175000017500000000267312222576535020143 0ustar frankfrank Block ciphers use one of the following four encryption modes: itemization( itb(CBC (Cipher Block Chaining)) The first block is XOR-ed by the initialization vector and then encrypted using the specified method. Subsequent blocks are XOR-ed by the encrypted version of the preceding block. Due to the initialization vector dictionary attacks are infeasible, as long as the initialization vector is truly random. itb(ECB (Electronic Code Book)) Each block is encrypted by itself, using the specified encryption method. Although an em(initialization vector) may be specified, it is not used. This method is susceptible to dictionary attacks and should therefore be avoided, unless you know what you're doing. itb(CFB (Cipher Feednack)) This method allows a block cipher to be used as a stream cipher. It uses an initialization vector, which should be unique and random for each new stream of data that is encrypted using the method. Encryption can only start after the first data block has been received. itb(OFB (Output Feednack)) This is an alternative way to use a block cipher as a stream cipher. It is somewhat more susceptible to traditional data manipulation attacks, which can usually be thwarted when a message authentication code is added to the information as well. Like CFB it uses an initialization vector, which should again be unique and random for each new stream of data that is encrypted. ) bobcat-3.19.01/documentation/man/cidr.yo0000644000175000017500000001316612222576535017041 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Cidr)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (CIDR matching) manpagename(FBB::Cidr)(Compares IP4 addresses to CIDR specifications) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() Objects of the class tt(Cidr) can be used for testing whether IP4 Internet addresses belong to address ranges defined by Classless Inter-Domain Routing (CIDR) address block specifications. CIDR blocks are specified as tt(a.b.c.d/m) where tt(a.b.c.d) are the four octets of a dotted decimal IP4 address specification (e.g., 129.125.14.80) and tt(m) is a mask-size (ranging from 0 to 32) defining the number of most significant bits to remain as-is. The CIDR specification 129.125.14.80/16 defines a class B network, with addresses ranging from 129.125.0.0 to 129.125.255.255. The mask size does not have to be a multiple of 8. E.g., when specifying 129.125.14.80/5 only the most significant 5 bits of the first octed are fixed, resulting in an address range ranging from 128.0.0.0 to 135.255.255.255. CIDR specifications passed to a tt(Cidr) object must be of the form tt(a.b.c.d) or tt(a.b.c.d/m). If the mask is not specified a mask-size of 32 is used, effectively defining an address range of only one address. Mask values of 0 are ignored. Mask values of 0 are ignored by tt(Cidr) objects. When specifying CIDRs on a stream, empty lines and comment lines (having a hash-character (#) as their first non-blank character) are ignored. Non-empty lines must start with a CIDR specification, and the tt(Cidr) object will ignore all information on a line trailing a CIDR specification. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) itemization( itb(Cidr(std::string const &cidrPattern)) The tt(Cidr) object is initialized with a single CIDR specification. itb(Cidr(std::istream &cidrStream)) The tt(Cidr) object is initialized with CIDR specifications read from the tt(std::istream cidrStream). ) The default, copy and move constructors are available. manpagesection(OVERLOADED OPERATORS) The copy and move assignment operators are available. manpagesection(MEMBER FUNCTIONS) The return valuess of the accessors (i.e., the tt(const) members) are only defined following a successful match (see below, the tt(match) members). itemization( itb(std::string const &address() const) returns the address matching a CIDR. itb(std::string cidr() const) returns the CIDR containing a specified address. itb(std::string first() const) returns the first address of the range of addresses defined by the CIDR specification. itb(std::string last() const) returns the last address of the range of addresses defined by the CIDR specification. Note that tt(first, last) do not define an iterator range. The address returned by tt(last) still belongs to the CIDR-range. itb(bool match(std::istream &in)) The value tt(true) is returned when an IP4 address found in the lines of tt(in) belongs to a CIDR range inspected by the tt(Cidr) object. The tt(match) function returns tt(true) at the first matching address. E.g., if a line contains the text verb( This is address 1.2.3.4 and this is 5.6.7.8 ) and the CIDR specifications verb( 5.1.1.1/8 1.2.1.1/16 ) were provided to the tt(Cidr) object, then the object will report a match for tt(5.6.7.8). As soon as a match is found tt(match) returns tt(true). If none of the addresses found in the lines of tt(in) matches any of the object's CIDR specifications, tt(false) is returned. itb(std::string mask() const) returns the mask used by the tt(CIDR) specification. itb(bool match(std::string const &line)) The value tt(true) is returned when an IP4 address found in tt(line) belongs to a CIDR range inspected by the tt(Cidr) object. The tt(match) function returns tt(true) at the first matching address. If none of the addresses found in tt(line) matches any of the object's CIDR specifications, tt(false) is returned. itb(void setCidr(std::istream &cidrStream)) A new set of CIDR specification is loaded into the tt(Cidr) object, reading the specifications from tt(cidrStream). itb(void setCidr(std::string const &cidrPattern)) A new CIDR specification is loaded into the tt(Cidr) object, using the specification found in tt(cidrPattern). The tt(Cidr) object is initialized with a single CIDR specification which must be of the form tt(a.b.c.d) or tt(a.b.c.d/m). If the mask is not specified a mask-size of 32 is used, effectively defining an address range of only one address. Mask values of 0 are ignored. ) manpagesection(STATIC MEMBERS) itemization( itb(size_t dotted2binary(std::string const &dotted)) Converts "a.b.c.d" to a 32-bits value itb(std::string binary2dotted(size_t binary)) Converts a 32-bits value to a dotted decimal IP4 address ) manpagesection(EXAMPLE) verbinclude(../../cidr/driver/driver.cc) manpagefiles() em(bobcat/cidr) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() Members of tt(Cidr) use static data. The current implementation of tt(Cidr) is therefore not thread-safe. includefile(include/trailer) bobcat-3.19.01/documentation/man/ptriter.yo0000644000175000017500000000657412222576535017616 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::PtrIter)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Error handler) manpagename(FBB::PtrIter)(Iterator returning pointer when dereferenced ) manpagesynopsis() bf(#include )nl() manpagedescription() The tt(PtrIter) class template implements an input iterator whose tt(operator*) returns the address of the element the iterator refers to. Consider a tt(std::unordered_map). Its tt(begin) member returns an iterator whose tt(operator*) returns a tt(std::pair (const) &). This is usually what you want, but now assume we want to display the map's contents, sorted by its keys. Sorting can simply be performed by defining a support vector containing pointers to the elements in the map, and then sorting the strings the pointers point at. tt(PtrIter) is a tool that can be used to construct such a support vector, as shown in the bf(EXAMPLE) section. tt(PtrIter) is a class template requiring one template type parameter: tt(Iterator), the iterator's type (e.g., tt(vector::iterator)) tt(PtrIter)'s users don't have to specify tt(PtrIter)'s template type. The function template tt(ptrIter), when provided with an iterator returns the matching tt(PtrIter) object. includefile(include/namespace) manpagesection(INHERITS FROM) tt(std::iterator) manpagesection(FREE FUNCTION) itemization( itb(PtrIter ptrIter(Iterator const &iter)) this function template returns a tt(PtrIter) object for the function's tt(Iterator) argument. This function template simplyfies the construction of a tt(PtrIter) as no template parameters need to be specified (see also the bf(EXAMPLE) section) ) manpagesection(CONSTRUCTORS) itemization( itb(PtrIter(Iterator const &iter)) The tt(iter) parameter must be initialized with an existing input iterator, offering tt(operator*, operator++, operator==) and tt(operator!=). As tt(PtrIter) is a class template, its template type parameters must be specified when defining a tt(PtrIter) object. E.g., verb( PtrIter::iterator> PtrIter(mySet.begin()); ) ) The copy and move constructors are available. manpagesection(OVERLOADED OPERATORS) itemization( itb(PtrType operator*() const) the address of the entity the iterator refers to is returned; itb(PtrIter &operator++()) the iterator is (pre)incremented to the next position; itb(bool operator==(PtrIter const &other) const) tt(true) is returned if the two iterators are equal; itb(bool operator!=(PtrIter const &other) const) tt(true) is returned if the two iterators are unequal; ) The copy and move assignment operators are available. manpagesection(DEFINED TYPE) tt(PtrIter) defines the following type: itemization( itb(typedef decltype(&*Iterator()) PtrType) ) manpagesection(MEMBER FUNCTIONS) All members of tt(std::iterator) are available, as bf(FBB::PtrIter) inherits from this class. manpagesection(EXAMPLE) verbinclude(../../ptriter/driver/driver.cc) manpagefiles() em(bobcat/ptriter) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/encryptbuf.yo0000644000175000017500000001753412222576535020304 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::EncryptBuf)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Encrypt information) manpagename(FBB::EncryptBuf) (Encrypts information using various methods into a std::ostream) manpagesynopsis() bf(#include )nl() Linking option: tt( -lbobcat) manpagedescription() bf(FBB::EncryptBuf) objects are bf(std::streambuf) objects that can be used to initialize tt(std::ostream) objects with. All information inserted into such a tt(std::ostream) is encrypted and written into a tt(std::ostream) that is given as argument to tt(EncryptBuf)'s constructor. All encryption methods defined by the OpenSSL library that can be selected by name may be used in combination with tt(EncryptBuf) objects. To select a particular encryption method an identifier is passed to the constructor. E.g., tt("aes-128-cbc") indicating the AES (Rijndael) method, using 128 bit sized keys and blocks using `cbc' mode (see below for an explanation). When providing shorter keys than expected by the method the provided key is extended by adding the required number of 0-bytes. (zero valued bytes, not tt('0') characters). Most modes use an em(initialization vector). Unless provided at construction time or explicitly set thereafter an initialization vector containg randomly selected values will be used. The initialization vector that is actually used can be obtained from the tt(EncryptBuf) object. This is important, as the matching decrypting object needs to know the initialization vector that was used when encrypting the data. Initialization vectors are not security sensitive in the sense that they can be sent in the clear to the decryption object. What em(is) important, though, is that they contain random data when used `for real'. When an initialization vector is specified that is shorter than expected by the method it will be extended with the required number of 0-bytes. includefile(blockciphers) includefile(symcryptciphers) includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(CONSTRUCTOR) itemization( itb(EncryptBuf(std::ostream &outStream, char const *type, std::string const &key, std::string const &iv, size_t bufsize = 1024)) This constructor initializes the tt(EncryptBuf) object preparing it for the message encrypt algorithm specified with tt(type). The encryption algorithms that can be used are listed in the table found in the bf(DESCRIPTION) section. E.g., to use the AES method on 24 bit keys and blocks in CBC mode specify tt("aes-192-cbc"). The tt(key) parameter refers to the key to be used, the tt(iv) parameter refers to the initialization vector to use. Both tt(key) and tt(iv) may contain non-displayable characters. When tt(iv.length()) is zero at the time encryption starts it will be filled by the tt(EncryptBuf) object with random data. When the key and/or the iv is too small for the requested method they will be expanded by adding the required number of zero valued bytes. The constructor throws an tt(FBB::Exception) exception if an unknown encryption method was specified. The constructor's first parameter refers to the tt(std::ostream) to receive the encrypted information. Be aware of the fact that the encrypted information most likely contains non-displayable characters. The tt(bufsize) argument specifies the size in bytes of the internal buffer used by tt(EncryptBuf) to store incoming characters temporarily. The provided default argument should be OK in all normal cases. ) There is no copy constructor, nor move constructor (as tt(std::streambuf) doesn't support either). manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::EncryptBuf) inherits from this class. Some of the bf(std::streambuf)'s member are overridden or are hidden by tt(EncryptBuf). In normal situations these inherited members will not be used by programs using tt(EncryptBuf) objects. itemization( itb(size_t blockLength() const) This member returns the block size (in bytes) that are used by the specified method. itb(size_t ivLength() const) This member returns the size (in bytes) of the initialization vector that is used by the specified method. itb(std::string iv() const) This member returns a reference to the initialization vector that is used by the specified method. Be advised that the initialization vector may contain non-displayable characters. itb(size_t keyLength() const) This member returns the size of the key (in bytes) that are used by the specified method. itb(size_t rounds() const) This member can only be used with the RC5 encryption method to query the number of rounds of the algorithm. It returns the currently used number of rounds or 0 if the member is called for another encryption method than RC5. itb(void setIv(std::string const &iv)) This member can be used to specify the initialization vector to use after construction time but before any data has been encrypted. When called after encryption has started an tt(FBB::Exception) exception will be thrown. itb(void setKey(std::string const &key, size_t numberOfBytes = 0)) This member can be used to specify the key and its length after construction time but before any data has been encrypted. When called after encryption has started an tt(FBB::Exception) exception will be thrown. The size of the key is assumed to be the number of bytes in the key's data. If another key length is required the member function's second parameter can be used to specify the length of the key em(in bytes). itb(bool setRounds(size_t nRounds)) This member can only be used with the RC5 encryption method to set the number of rounds of the algorithm to 8, 12 or 16. When the number of rounds were updated successfully the member returns tt(true). It returns tt(false) in other cases (e.g., called for other encryption methods than RC5 or the requested number of rounds differ from 8, 12 or 16). ) manpagesection(PROTECTED MEMBER) itemization( itb(EVP_CIPHER_CTX *cipherCtx()) Classes derived from tt(EncryptBuf) may use this member to gain direct access to the tt(EVP_CIPHER_CTX) pointer used by the tt(EncryptBuf) object. This pointer is a pointer to an opaque structure used by many OpenSSL functions to set or query parameters of an encryption method. ) manpagesection(EXAMPLE) verbinclude(../../encryptbuf/driver/driver.cc) To ignore the initial 256 bytes generated by the RC4 algorithm a simple wrapper class around the eventual output stream can be used. Here is an illustration: verb( #include #include class Skip256: public FBB::OFilterStreambuf { size_t d_count; public: Skip256(std::ostream &os) : OFilterStreambuf(os), d_count(0) {} private: virtual int overflow(int c) { if (d_count == 256) out().put(c); else ++d_count; return c; } }; ) Next, an tt(Skip256) object is used to define an intermediate tt(std::ostream) that is then passed to the tt(EncryptBuf) object. E.g., only showing the essential steps defining the tt(EncryptBuf) object: verb( Skip256 skip256(std::cout); std::ostream out(&skip256); EncryptBuf encryptbuf(out, "rc4", key, ""); ) manpagefiles() em(bobcat/encryptbuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(decryptbuf)(3bobcat), bf(ofilterstreambuf)(3bobcat), bf(std::streambuf) manpagebugs() None reported includefile(include/trailer) bobcat-3.19.01/documentation/man/gethostent.yo0000644000175000017500000001023512222576535020276 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::GetHostent)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Host information) manpagename(FBB::GetHostent) (Obtain bf(hostent) struct from hostname or -address) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::GetHostent) objects produce tt(hostent) structs which may be used by other types of objects. The bf(FBB::GetHostent) class is therefore primarily used as a base-class for other classes and is seldomly used `stand-alone'. The tt(hostent) structs are static structs, but a non-static copy may be obtained using an bf(FBB::Hostent) object. A tt(hostent) struct is defined as follows: verb( struct hostent { char *h_name; // official name of host char **h_aliases; // alias list int h_addrtype; // host address type (always AF_INET) int h_length; // length of address char **h_addr_list; // list of addresses } ) The tt(address) fields are binary values of the addresses, each address requiring tt(h_length) bytes, the last address being equal to 0. These binary values may be converted to character-representations by the tt(addressToString()) member, which uses bf(inet_ntop()), internally. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) All members of the class bf(FBB::GetHostent) are static. Consequently, there is no need to construct a bf(FBB::GetHostent) object. However, the default- and copy-constructors are available. manpagesection(STATIC MEMBERS) itemization( itb(hostent const *gethostent(char const *errorprefix, std::string const &nameOrAddress)) The bf(gethostent()) member returns a pointer to a static bf(struct hostent). It contains the information about the host whose name or dotted decimal address was provided as its second argument. Its first argument is an error string prefix, prefixing the error message in an bf(FBB::Exception) object. Such an object is thrown as an exception when the host's information could not be retrieved. itb(std::string addressToString(char const *errorprefix, void const *ads)) This member returns the dotted decimal address of the host whose binary address is provided at bf(ads). Its first argument is an error string prefix, prefixing the error message in an bf(FBB::Exception) object. Such an object is thrown as an exception when the dotted decimal address could not be determined. The class' members can only be used when the host whose name or address is searched can be resolved by a name resolution process, e.g., bf(bind)(1). ) manpagesection(EXAMPLE) verb( #include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { if (argc == 1) { cerr << "Provide a host name or host address to solve\n"; return 1; } try { Hostent he(GetHostent::gethostent(argv[1], argv[1])); cout << "Hostname: " << he.hostname() << endl; cout << "Aliases:\n"; copy(he.beginAlias(), he.endAlias(), ostream_iterator(cout, "\n")); cout << "Addresses:\n"; for (size_t idx = 0; idx < he.nAddresses(); idx++) cout << he.dottedDecimalAddress(idx) << endl; } catch (Exception const &err) { cout << err.what() << endl; return 1; } return 0; } ) manpagefiles() em(bobcat/gethostent) - defines the class interface manpageseealso() bf(bind)(1), bf(bobcat)(7), bf(gethostbyaddr)(3) bf(gethostbyname)(3), bf(hostent)(3bobcat), bf(inetaddress)(3bobcat), bf(inet_ntop)(3) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/hostname.yo0000644000175000017500000000363612222576535017737 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Hostname)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Host Info) manpagename(FBB::Hostname)(Contains name/address info about a host) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::Hostname) objects inherit from tt(Hostent), and offers information about a host, like bf(Hostent). Apart from being initialized by a hostname or host address, they can also be initialized by a bf(FBB::InetAddress) object. Most of the functionality of an bf(FBB::Hostname) object is available through its parent-class bf(FBB::Hostent). includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::Hostent) manpagesection(CONSTRUCTORS) itemization( itb(Hostname()) The default constructor initializes an empty bf(FBB::Hostname) object. itb(Hostname((std::string const &host))) This constructor initializes an bf(FBB::Hostname) object from a string representing the name or dotted decimal address of a host. An bf(FBB::Exception) object is thrown if the hostname information could not be retrieved. itb(Hostname(InetAddress const &inetAddress)) This constructor initializes an bf(FBB::Hostname) object from an bf(InetAddress) object. An bf(FBB::Exception) object is thrown if the hostname information could not be retrieved. ) The copy constructor is available. manpagesection(MEMBER FUNCTIONS) All members of bf(FBB::Hostent) are available, as bf(FBB::Hostname) inherits from this class. There are no additional members. manpagesection(EXAMPLE) verbinclude(../../hostname/driver/driver.cc) manpagefiles() em(bobcat/hostname) - defines the class interface manpageseealso() bf(bobcat)(7), bf(hostent)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/include/0000755000175000017500000000000012257522663017164 5ustar frankfrankbobcat-3.19.01/documentation/man/include/trailer.yo0000644000175000017500000000142512222576535021200 0ustar frankfrank manpagesection(DISTRIBUTION FILES) itemization( itt(bobcat__CurVers_-x.dsc): detached signature; itt(bobcat__CurVers_-x.tar.gz): source archive; itt(bobcat__CurVers_-x_i386.changes): change log; itt(libbobcat1__CurVers_-x_*.deb): debian package holding the libraries; itt(libbobcat1-dev__CurVers_-x_*.deb): debian package holding the libraries, headers and manual pages; itt(http://sourceforge.net/projects/bobcat): public archive location; ) manpagesection(BOBCAT) Bobcat is an acronym of `Brokken's Own Base Classes And Templates'. manpagesection(COPYRIGHT) This is free software, distributed under the terms of the GNU General Public License (GPL). manpageauthor() Frank B. Brokken (bf(f.b.brokken@rug.nl)). bobcat-3.19.01/documentation/man/include/namespace.yo0000644000175000017500000000025012222576535021465 0ustar frankfrankmanpagesection(NAMESPACE) bf(FBB)nl() All constructors, members, operators and manipulators, mentioned in this man-page, are defined in the namespace bf(FBB). bobcat-3.19.01/documentation/man/include/header.yo0000644000175000017500000000136212257522663020767 0ustar frankfrankDEFINEMACRO(Manpage)(1)(\ whenman((Manpage: tt(man -e bobcat ARG1)))\ whenhtml((Manpage: url(ARG1(3bobcat))(ARG1.3.html)))\ ) DEFINEMACRO(verbinsert)(2)(\ PIPETHROUGH(yodlverbinsert //ARG1 ARG2)()\ ) DEFINEMACRO(itb)(1)(it() bf(ARG1):nl()) DEFINEMACRO(itt)(1)(it() tt(ARG1)) DEFINEMACRO(itrange)(2)(tt(CHAR(91)ARG1, ARG2+CHAR(41))) includefile(../../../release.yo) htmlbodyopt(text)(#27408B) htmlbodyopt(bgcolor)(#FFFAF0) whenhtml(mailto(Frank B. Brokken: f.b.brokken@rug.nl)) DEFINEMACRO(lsoption)(3)(\ bf(--ARG1)=tt(ARG3) (bf(-ARG2))\ ) DEFINEMACRO(loption)(1)(\ bf(--ARG1)\ ) DEFINEMACRO(soption)(1)(\ bf(-ARG1)\ ) DEFINEMACRO(ix)(0)(bf(imgx)) DEFINEMACRO(Ix)(0)(bf(Imgx)) DELETEMACRO(tt) DEFINEMACRO(tt)(1)(em(ARG1)) bobcat-3.19.01/documentation/man/fswap.yo0000644000175000017500000001260512222576535017235 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::fswap)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Fast swap function) manpagename(FBB::fswap)(generic template fast swap function) manpagesynopsis() bf(#include )nl() manpagedescription() The information stored in objects frequently needs to be swapped. A well-known example is the swapping operation required when implementing an overloaded assignment operator. For example, the generic form of the operator assignment operator is: verb( Class &operator=(Class const &other) { Class tmp(other); swap(tmp); return *this; } ) The swap functionality merely swaps the contents of the current object and another object. The standard tt(std::swap) function calls the class's tt(operator=) function to swap objects. Newer implementations might use move-operations to increase the speed of the swaping operation, but in both cases some form of the assignment operator must be available. Swapping, however, might be possible when assignemnt isn't. Classes having reference data members usually don't offer assignment operators but swapping might be a well-defined operation. It is well known that objects can be installed in a block of memory using em(placement new), using a block of memory the size of the object to construct the object it. This is the foundation of the template function tt(FBB::fswap) (fast swap). This swap function merely uses the memory occupied by objects to implement the swapping operation and it may therefore be used with classes having const data members, reference data members, ponters to allocated memory etc, etc. The function simply uses a spare block of memory the size of the object to be swapped. It then uses bf(memcpy)(3) to swap the information contained in the two objects, using the spare block of memory as a placeholder. The function uses partial specializations to optimize the swapping operation for objects of sizes 1, 2, 4 or 8 bytes. It uses bf(memcpy)(3) for objects of other sizes. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(SWAP FUNCTION) itemization( itb(fswap(Type &lhs, Type &rhs)) This template function swaps the contents of the two objects. It can be used with classes having const data members, reference members, pointer members or standard value-typed data members. ) manpagesection(EXAMPLE) verbinclude(../../fswap/driver/driver.cc) manpagefiles() em(bobcat/fswap) - defines the class interface manpageseealso() bf(bobcat)(7), bf(memcpy)(3) manpagebugs() The tt(fswap) function should not be applied mechanically to swap objects of classes having pointer data members defining, e.g., a linked list. Consider a list of four objects like: verb( A -> B -> C -> D ) fast-swapping B and C would result in the following corrupted list: verb( +------+ | | A -> C -+ +-> B -+ +-> D | | +-------------+ ) However, classes implementing a data structure like a linked-list might still benefit from fast swapping operations: by implementing their own swap member they could first use fast swapping to swap the objects, followed by another fast swap to unswap their `next' pointers. The tt(fswap) function should also not be used for objects defining (back-)pointers to their own data. Consider the following objects using pointers to data and (back-)pointers to the original objects: verb( Before fswapping: A B +--------+ +-----------+ +--------+ +-----------+ | | | | | | | | +--> *Aimp------> *A (back)--+ +--> *Bimp------> *B (back)--+ | | | | | | | | | | | | +--**Aimp | +-----------+ | +--**Bimp | +-----------+ | +--------+ <---------------+ +--------+ <---------------+ After fswapping: +-------------------------------+ +--|-------------------------------|-+ +-------------|--|-----------------+ | | | A | v | B | v | +--------+ | +-----------+ | +--------+ | +-----------+ | | | | | | | | | | | | +-----> *Bimp---+ | *A (back)--+ +---> *Aimp---+ | *B (back)--+ | | | | | | | | | | | | | +---**Bimp | +-----------+ | +---**Aimp | +-----------+ | | +--------+ <---------------+ | +--------+ <---------------+ +------------------------------------+ ) After the swap tt(**Bimp) should point to tt(Bimp)'s address (now at A), but in fact it points to tt(Aimp)'s address (now at B). Likewise, the back pointers still point at their original objects rather than at their swapped objects. All tt(stream) classes define such pointers and can therefore not be swapped using tt(fswap). The bottom line being that tt(fswap) should only be used for self-defined classes for which it can be proven that fast-swapping does not corrupt the values of its pointer data. includefile(include/trailer) bobcat-3.19.01/documentation/man/ofilterstreambuf.yo0000644000175000017500000001434212222576535021472 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::OFilterStreambuf)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz)(ostream filtering) manpagename(FBB::OFilterStreambuf)(Base class for std::ostream filtering) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() The bf(FBB::OFilterStreambuf) class is a specialization of the tt(std::streambuf) class and can be used as a base class for classes implementing em(ostream)-filtering. Ostream filtering is defined here as the process by which inserted characters are subject to processing before they are passed on to another (filtered) tt(ostream) object (or they may be rejected). The filtering may also result in inserting additional information into the filtered tt(ostream). em(Chaining) of filters is also possible: the filtered tt(ostream) may itself use an tt(OFilterStreambuf) to filter its received information before passing it on to yet another tt(ostream). As tt(OFilterStreambuf) inherits from tt(std::streambuf) an tt(OFilterStreambuf) object can be used to provide an tt(ostream) object with a tt(std::streambuf). Information inserted into such a stream travels the following route: itemization( it() The information is converted to characters using the standard conversion facilities implemented by tt(std::ostream) objects. E.g., when inserting the value tt(123) this value is converted to the characters tt('1', '2') and tt('3'), respectively. it() Each of the characters is then offered (in turn) to the tt(std::streambuf) that is associated with the tt(ostream) object. In particular, the tt(std::streambuf)'s tt(overflow()) member is called. it() tt(OFstreamBuf)'s default tt(overflow()) function ignores characters, but specializations can override tt(overflow()) to process the received characters em(ad lib). it() A overriding tt(overflow()) function has access to the member tt(OFstreambuf::out()) which is a reference to the tt(std::ostream) receiving the filtered information. ) To implement a simple copy-filter (i.e., all characters are accepted as-is) a class must be derived from tt(OFilterStreambuf) providing an overriding implementation of tt(overflow()), e.g., as follows: verb( int DerivedClass::overflow(int ch) { out().put(ch); } ) Next this tt(std::streambuf) specialization can be associated with an tt(ostream) into which information to be `copy filtered' can be inserted (cf. the EXAMPLE section below). includefile(include/namespace) manpagesection(INHERITS FROM) std::streambuf manpagesection(CONSTRUCTORS) itemization( itb(OFilterStreambuf()) This constructor creates a tt(OFilterStreambuf) object without associating it with a destination (filtered) tt(ostream). itb(OFilterStreambuf(std::string const &fname, openmode mode = std::ios::out)) This constructor creates a tt(OFilterStreambuf) object and opens a private tt(std::ofstream) object whose filename is provided and that should receive the filtered information. itb(OFilterStreambuf(char const *fname, openmode mode = std::ios::out)) Same as the previous constructor, expecting a tt(char const *) defining the name of the private tt(std::ofstream) object. itb(OFilterStreambuf(std::ostream &out)) This constructor creates a tt(OFilterStreambuf) object and will insert any filtered information into the provided tt(ostream) object. ) The class's destructor closes the destination (filtered) stream (cf. the description of tt(close()) below). manpagesection(MEMBER FUNCTIONS) All members of bf(std::ostreambuf) are available, as bf(FBB::OFilterStreambuf) inherits from that class. In particular, derived classes should provide their own implementation of tt(int underflow(int ch)) to implement any non-trivial filtering. itemization( itb(void close()) This member calls the tt(streambuf::sync()) member to flush any pending information to the destination (filtered) stream and then closes the destination stream. Note that the default tt(sync()) member performs no special actions but it can be overridden by derived classes to flush the destination stream just prior to its closing. itb(void open(std::string const &fname, openmode mode = std::ios::out)) This member closes the current destination (filtered) tt(std::ostream) object and associates the tt(OFilterStreambuf) object with a private tt(std::ofstream) object whose filename is provided and that should receive subsequently filtered information. itb(void open(char const *fname, openmode mode = std::ios::out)) Same as the previous member, but using a tt(char const *) to specify the name of the private tt(std::ofstream) object to receive the filtered information. itb(void open(std::ostream &out)) This member closes the current destination (filtered) tt(std::ostream) object and associates the tt(OFilterStreambuf) object with the provided tt(ostream) object. ) manpagesection(PROTECTED MEMBER FUNCTION) itemization( itb(std::ostream &out() const) This member is available to derived classes to insert information into the destination (filtered) stream. ) manpagesection(EXAMPLE) verb( #include #include #include class NoDigits: public FBB::OFilterStreambuf { private: int overflow(int ch) override { if (not isdigit(ch)) out().put(ch); return ch; } int sync() override { out() << flush; return 0; } }; using namespace FBB; using namespace std; int main() { NoDigits nod(cout); // no digits to cout ostream out(&nod); out << in.rdbuf(); // rm digits from cin return 0; } ) manpagefiles() em(bobcat/ofilterstreambuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ifilterstreambuf)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/readlinebuf.yo0000644000175000017500000002745112222576535020402 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::ReadLineBuf)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz) (Editing input lines) manpagename(FBB::ReadLineBuf) (std::streambuf offering line-editing and history) manpagesynopsis() bf(#include )nl() Linking option: -lreadline -lbobcat manpagedescription() The bf(FBB::ReadLineBuf) object may be used as a tt(std::streambuf) of tt(std::istream) objects, allowing line-editing and history manipulation. The bf(ReadLineBuf) class uses Gnu's readline library to allow editing of input lines. The tt(ReadLineBuf) object can be used to construct a tt(std::istream) allowing in-line editing of lines read from the terminal. All lines may be preceded by a configurable prompt. Since Gnu's readline library operates on global data there can only be one bf(ReadLineBuf) object. Therefore bf(ReadLineBuf) is a singleton class: in any program there can only be one bf(ReadLineBuf) object (Gnu's readline library does, however, offer functions allowing programs to use multiple histories. So it would in principle be possible to design a non-singleton tt(ReadLineBuf) class. Since programs normally only interact with a single terminal, there is probably little use for non-singleton bf(ReadLineBuf) class). bf(ReadLineBuf) offers editing capabilities while the user is entering lines. Like Gnu's bf(readline)(3) function, the line editing commands are by default similar to those of bf(emacs)(1), but can easily be reconfigured, e.g. to offer bf(vi)(1)-like characteristics. History manipulation is provided as an option. The collected history may be accessed for reading using an bf(FBB::ReadLineHistory) object. Specific information about the facilities offered by the Gnu software used by bf(ReadLineBuf) is provided in the GNU Readline Library documentation (tt(http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html)). Gnu's tt(readline) function reads its information from the standard input file. Programs using tt(ReadLineBuf) should normally not extract information from tt(std::cin). However, as the standard input file has a file descriptor (0), redirection should be possible (e.g., using tt(FBB::Redirector)). When the command line is kept, history expansion is offered as an option. History expansion introduces words from the history list into the input stream, making it easy to repeat commands, to insert elements of a previous input line into the current input line, or to fix errors in previous command lines. History expansion is usually performed immediately after a complete line is read. The line selected from the history is called the tt(event), and the portions of that line that are processed are called tt(words). Various modifiers are available to manipulate selected words. This is comparable to the way a program like bf(bash)(1) breaks up its input line into `words'. History expansion is introduced by the use of the history expansion character, by default equal to the tt(!)-character. Only backslash (tt(\)) and single quotes can change the history expansion character into a normal character. The remainder of this section is copied almost verbatim from the bf(history)(3) man-page. The reader is referred to that man-page or to the Gnu History Library documentation for further details. The following bf(event designators) are supported: itemization( itt(!): starts a history substitution, except when followed by a blank, newline, tt(=) or tt(CHAR(40)). itt(!n): refers to command line n. itt(!-n): refers to the current command line minus n. itt(!!) refers to the previous command. This is a synonym for `!-1'. itt(!string) refers to the most recent command starting with string. itt(!?string[?]) refers to the most recent command containing string. The trailing tt(?) may be omitted if string is followed immediately by a newline. itt(^string1^string2^) (quick substitution) repeats the last command, replacing tt(string1) with tt(string2). Equivalent to tt(!!:s/string1/string2/). itt(!#) the entire command line typed so far. ) bf(Word Designators) Word designators are used to select desired words from the event. A tt(:) separates the event specification from the word designator. It may be omitted if the word designator begins with a tt(^, $, *, -), or tt(%). Words are numbered from the beginning of the line, with the first word being denoted by 0 (zero). Words are inserted into the current line separated by single spaces. itemization( itt(0) (zero) The zeroth word. For the shell, this is the command word. itt(n) The nth word. itt(^) The first argument. That is, word 1. itt($) The last argument. itt(%) The word matched by the most recent tt(?string?) search. itt(x-y) A range of words; `-y' abbreviates `0-y'. itt(*) All of the words but the zeroth. This is a synonym for tt(1-$). It is not an error to use * if there is just one word in the event; the empty string is returned in that case. itt(x*) Abbreviates tt(x-$). itt(x-) Abbreviates tt(x-$) like tt(x*), but omits the last word. ) If a word designator is supplied without an event specification, the previous command is used as the event. bf(Modifiers) After the optional word designator, there may appear a sequence of one or more of the following modifiers, each preceded by a tt(:). itemization( itt(h) removes a trailing file name component, leaving only the head. itt(t) removes all leading file name components, leaving the tail. itt(r) removes a trailing suffix of the form tt(.xxx), leaving the basename. itt(e) removes all but the trailing suffix. itt(p) prints the new command but does not execute it. itt(q) quotes the substituted words, escaping further substitutions. itt(x) quotes the substituted words as with q, but break into words at blanks and newlines. itt(s/old/new/) substitutes new for the first occurrence of old in the event line. Any delimiter can be used in place of tt(/). The final delimiter is optional if it is the last character of the event line. The delimiter may be quoted in old and new with a single backslash. If tt(&) appears in new, it is replaced by old. A single backslash will quote the tt(&). If tt(old) is null, it is set to the last old substituted, or, if no previous history substitutions took place, the last string in a tt(!?string[?]) search. itt(&) repeats the previous substitution. itt(g) Causes changes to be applied over the entire event line. This is used in conjunction with tt:s) (e.g., tt(:gs/old/new/)) or tt(:&). If used with tt(:s), any delimiter can be used in place of tt(/), and the final delimiter is optional if it is the last character of the event line. An a may be used as a synonym for tt(g). itt(G) Apply the following tt(s) modifier once to each word in the event line. ) includefile(include/namespace) manpagesection(INHERITS FROM) tt(std::streambuf) manpagesection(ENUMERATIONS) The tt(enum Type) defines the following value: itemization( itt(DONT_EXPAND_HISTORY): history expansion is not requested; itt(EXPAND_HISTORY): history expansion is requested. ) The tt(enum Expansion) provides meaningful return values for the history expansion process. Its values are: itemization( itt(DONT_EXEC): history expansion succeeded, but the expanded line should not be executed. E.g., after entering the line verb( ls * ) the line verb( !!:p ) should cause the using program to em(display), rather than exectute tt(ls *). Note that interpretation of this expansion return value is not the task of the bf(ReadLineBuf) object, but of the program using the bf(ReadLineBuf) object. itt(ERROR): the history expansion failed. See also the member tt(expansionError) below; itt(EXPANDED): the history expansion succeeded; itt(NO_EXPANSION): no history expansion took place. ) manpagesection(STATIC MEMBERS) itemization( itb(ReadLineBuf &initialize(std::string const &prompt = "", Type type = NO_EXPANSION)) This static member returns the tt(ReadLineBuf) using an initial prompt, using a history of at most tt(std::numeric_limits::max()) lines, and by default not using history expansion. If the object has already been initialized a tt(logic_error) exception is thrown. itb(ReadLineBuf &initialize(std::string const &prompt, size_t historySize, Type type = NO_EXPANSION)) This static member initializes the tt(ReadLineBuf) using an initial prompt, an initial history of a predefined maximum size, and by default not using history expansion. Specifying a history size 0 results in no history being kept, any value equal to or exceeding the predefined constant tt(std::numeric_limits::max()) results in a history of at most tt(std::numeric_limits::max()) lines. If no history is requested but tt(type) is specified as tt(EXPAND_HISTORY) a tt(logic_error) exception is thrown. A tt(logic_error) is also thrown if the object has already been initialized. itb(ReadLineBuf &instance()) This static member returns the already initialized tt(ReadLineBuf) object. If the object has not yet been initialized a tt(logic_error) exception is thrown. ) manpagesection(CONSTRUCTORS) As the class bf(ReadLineBuf) is a singleton class it offers no public constructors. manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::ReadLineBuf) inherits from this class. itemization( itb(ReadLineBuf::Expansion expansion() const) The status of the history expansion after retrieving a line from the terminal is returned. Its value is determined after each line retrieved from the terminal. If no history expansion is requested it returns tt(Expansion::ERROR). itb(std::string const &expansionError() const) A short textual description of the nature of the error when tt(expansion) returns tt(Expansion::ERROR) is returned. If no history expansion is requested an empty string is returned. itb(bool setExpansion(Type type)) History expansion can be activated or stopped using this member. When history expansion is requested but the bf(ReadLineBuf) object maintains no history the function returns tt(false). Otherwise it returns tt(true). itb(void setPrompt(std::string const &prompt = "")) The prompt that is displayed in front of the next line read from the terminal can be modified by this member. When called without arguments no prompt will be displayed. tt(setPrompt) can be called while input lines are being received. The new prompt will be active after the current line has been read from the terminal. itb(bool useTimestamps(std::string (*timestamp)() = 0)) When initialized with the address of a function returning a tt(std::string) the entered commands will be given a timestamp equal to the text returned by the function pointed to by tt(timestamp). The timestamps can be retrieved using the bf(ReadLineHistory)(3) object. By default or after passing an explicit 0-pointer to tt(useTimestamps) no timestamps are stored. The value tt(false) is returned when no history is kept, otherwise tt(true) is returned. ) manpagesection(EXAMPLE) verbinclude(../../readlinebuf/driver/driver.cc) manpagefiles() em(bobcat/readlinebuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(readline)(3), bf(readlinehistory)(3), bf(readlinestream)(3) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/x2a.yo0000644000175000017500000000727312222576535016614 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::X2a)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (X-to-ASCII conversions) manpagename(FBB::X2a)(Objects performing x-to-Ascii conversions) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB:X2a) objects convert values of any (insertable) type to text. The returned text is automatically made available as a standard bf(C++) string. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::ostringstream) manpagesection(CONSTRUCTORS) itemization( itb(X2a(T const &value)) In this constructor tt(T) may be any type that can be inserted into an tt(o[string]stream). itb(X2a(double value, size_t behind)) Double tt(value) is truncated to tt(behind) digits behind the decimal dot. If a value doesn't occupy tt(behind) digits behind the decimal point, then missing digits are added as tt(0). For example, a value of 7.1, will be displayed as 7.10 if two digits behind the decimal dot are requested. A value of 7 will be displayed as 7.00. itb(X2a(double value, size_t width, size_t behind, std::ios::fmtflags flags = std::ios::right)) The value is displayed over tt(width) character positions, extending the amount if the value so requires. The converted value is placed right-aligned into the field of tt(width) characters. ) The copy constructor is available as well. manpagesection(STATIC MEMBER FUNCTION) itemization( itb(bool lastFail()) This member returns tt(true) if the last conversion failed (i.e., the object's tt(fail()) member returned tt(true) and returns tt(false) otherwise). This member allows checks on the success of the extraction/conversion using anonymous tt(A2x) objects. The member also returns tt(true) when no conversions have as yet been performed.nl() Note that this member is a thread-unsafe em(static) member: in a multithreaded program locks may be required to ensure that the proper conversion result is inspected. ) manpagesection(MEMBER FUNCTIONS) All members of bf(std::ostringstream) are available, as bf(FBB::X2a) inherits from this class. In particular tt(ostringstream::str()) can be used to obtain the contents of an tt(X2a) object's text buffer. manpagesection(OVERLOADED OPERATORS) itemization( itb(operator std::ostream &operator<<(std::ostream &ostr, X2a const &x2a)) This conversion operator inserts the textual representation of the tt(x2a) parameter value into the provided tt(ostream). itb(operator std::string const() const) this conversion operator returns the information stored inside the bf(FBB::X2a) object. ) The standard overloaded assignment operator is available as well. manpagesection(EXAMPLE) verb( string is(X2a(5)); // initializes `is' with "5" string ds(X2a(5.25)); // initializes `ds' with "5.25" cout << X2a(7.0 / 3, 4) << endl; // display a value using 4 digits behind the // decimal dot. cout << X2a(7.0 / 3, 8, 4) << endl; // display a value over 8 positions, right // adjusted, 4 digits behind the decimal dot. cout << X2a(7.0 / 3, 8, 4, std::ios::left) << endl; // display a value over 8 positions, left // adjusted, 4 digits behind the decimal dot. ) manpagefiles() em(bobcat/x2a) - defines the class interface manpageseealso() bf(bobcat)(7), bf(a2x)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/syslogbuf.yo0000644000175000017500000002112412222576535020126 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Syslogbuf)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Stream Buffer for Syslog) manpagename(FBB::Syslogbuf)(A streambuf object inserting syslog messages) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() Addresses of bf(FBB::Syslogbuf) objects can be passed as bf(std::streambuf) addresses to tt(std::ostream) objects to write messages to the syslog daemon using stream facilities. Multiple separate insertions can be used to create a single syslog message: the message is only sent to the syslog daemon after receiving a tt(flush) command (e.g., after inserting tt(std::flush) or tt(std::endl)). Non-printable characters (like tt('\n')) show up in the syslog message as octal values, preceded by tt(#) (e.g., tt(#012) for tt('\n')). The newline normally inserted by tt(std::endl) is ignored: bf(SyslogStream) objects interpret tt(std::endl) like tt(std::flush). One series of insertions may contain multiple tt(std::endl) or tt(std::flush) manipulators. At each of these manipulators a new message is sent to the syslog daemon, containing all info that has so far been buffered. After sending a message to the syslog daemon, the bf(SyslogStream)'s internal buffer is cleared. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(ENUMERATIONS) The following enumerations are defined in the namespace bf(FBB): bf(Priority): The values of this enumeration match the corresponding priority bf(LOG_xxx) values used with bf(syslog)(3): itemization( itb(EMERG) system is unusable; itb(ALERT) action must be taken immediately; itb(CRIT) critical conditions; itb(ERR) error conditions; itb(WARNING) warning conditions; itb(NOTICE) normal, but significant, condition; itb(INFO) informational message; itb(DEBUG) debug-level message; ) bf(PriorityType): This enumberation has two values fine-tuning the type of messages that are actually processed by the syslog daemon: itemization( itb(SINGLE) Only messages of the priority specified at the tt(setMask) call are processed by the syslog daemon; itb(UPTO) Messages of priority tt(EMERG) up to the the priority specified at the tt(setMask) call are processed by the syslog daemon; ) By default, the syslog daemon processes all messages it receives. bf(Facility): The values of this enumeration match the corresponding facility bf(LOG_xxx) values used with bf(syslog)(3): itemization( itb(AUTHPRIV) security/authorization messages (private) itb(CRON) clock daemon (tt(cron) and tt(at)) itb(DAEMON) other system daemons itb(KERN) kernel messages itb(LOCAL0) reserved for local use. bf(LOCAL1) through bf(LOCAL7) are available as well. itb(LPR) line printer subsystem itb(MAIL) mail subsystem itb(NEWS) tt(USENET) news subsystem itb(SYSLOGBUF) messages generated internally by tt(syslogbufd) itb(USER) generic user-level messages itb(UUCP) UUCP subsystem ) manpagesection(CONSTRUCTORS) itemization( itb(Syslogbuf(string const &ident = "", FBB::Priority priority = FBB::NOTICE, FBB::Facility facility = FBB::USER, int option = 0)) This constructor initializes a bf(Syslogbuf) object. The tt(ident) parameter is usually the name of the program. Its contents are prepended to syslog messages. The tt(priority) parameter determines the default importance of the message sent to the syslog daemon. By default messages are sent to the syslog daemon with priority bf(FBB::NOTICE). Syslog messages may be given different priority by inserting a bf(SyslogStream)(3bobcat) manipulator. The priority set at construction time may also be modified using the tt(setPriority) and tt(setDefaultPriority) members. Which messages actually appear in log facilities is not determined by the messages' priorities, but by syslog's em(log mask). The log mask can be set by the static member tt(setMask) (see below). The tt(facility) parameter determines the type of program doing the logging. By default bf(FBB::USER) is used. The tt(option) parameter may be used to specify various options (use the binary `tt(bitor)' (`tt(|)') operator to combine options): bf(LOG_CONS): write directly to system console if there is an error while sending to system logger nl() bf(LOG_NDELAY): open the connection immediately (normally, the con- nection is opened when the first message is logged) nl() bf(LOG_PERROR): print to stderr as well nl() bf(LOG__PID): include PID with each message nl() By default no options are used. itb(Syslogbuf(char const *ident, FBB::Priority priority = FBB::NOTICE, FBB::Facility facility = FBB::USER, int option = 0)) This constructor is kept for backward compatibility. Its parameters have the same meanings as those of the abovementioned constructor. A tt(nullptr) indicates that no text needs to be prepended to syslog messages. ) Copy and move constructors are not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::Syslogbuf) inherits from this class. itemization( itb(void close()) If the bf(SyslogStream)'s internal buffer is not empty it is flushed to the syslog daemon. Thereafer bf(closelog)(3) is called. itb(Priority defaultPriority() const) Returns the current default priority. I.e., the priority that will be used for the messages after inserting tt(endl) or tt(flush). itb(void open(string const &ident, FBB::Priority priority = FBB::NOTICE, FBB::Facility facility = FBB::USER, int option = 0)) Redefines the current identifier, priority, facility and options that are used when sending messages to the syslog daemon. If the bf(SyslogStream)'s internal buffer is not empty it is first flushed to the syslog daemon using the identifier, priority and options that were active just before calling tt(open). itb(Priority priority() const) Returns the next priority. I.e., the priority that will be used for the next message that is sent to the syslog daemon. itb(Priority setDefaultPriority(Priority priority)) Changes the default priority of the next message that is sent to the syslog daemon after inserting tt(std::eoln) or tt(std::flush). The previously active default priority is returned. itb(Priority setPriority(Priority priority)) Changes the priority for the next message that is sent to the syslog daemon after inserting tt(std::eoln) or tt(std::flush). Subsequent messages will again use the default priority. The previously active priority setting is returned. ) manpagesection(PROTECTED MEMBER FUNCTION) The member listed in this section implements the tasks of the comparably named virtual function in the class's private interface. This separates the redefinable interface from the user-interface. The class bf(Syslogbuf) can, in accordance with Liskov's Substitution Principle, be used as a tt(std:streambuf); but it also offers a facility for classes deriving from bf(Syslogbuf). itemization( itb(int pSync()) The contents of the bf(Syslogbuf)'s internal buffer are flushed to the syslog daemon. ) manpagesection(EXAMPLE) See also bf(syslogstream)(3bobcat) verb( #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { ostream sls(new Syslogbuf(argv[0])); sls << SyslogStream::debug << "Hello world" << flush << SyslogStream::strerrno << endl; } ) manpagefiles() em(bobcat/syslogbuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(closelog)(3), bf(openlog)(3), bf(rsyslogd)(8) bf(syslog)(3), bf(syslogstream)(3bobcat) manpagebugs() The constructor's tt(option) parameter is an tt(int). Because of this, tt(int) values rather than enumeration values are passed to the constructor. It is the responsibility of the programmer to pass defined option values only. includefile(include/trailer) bobcat-3.19.01/documentation/man/binops.yo0000644000175000017500000001325612222576535017412 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(binops)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Binary Operators) manpagename(binops)(Template functions for class-type binary operators) manpagesynopsis() bf(#include )nl() bf(#include )nl() bf(#include )nl() manpagedescription() Classes can overload binary operators. A class named tt(Class) may overload these binary operators to suit its own needs, allowing, e.g., two tt(Class) type objects to be added after overloading tt(operator+). Operators for the binary operators *, /, %, +, -, <<, >>, &, |, and ^ (in this man-page they are generically indicated as the `tt(@)' operator) can be overloaded by defining the tt(operator@) function. If a class supports copy construction and if it offers binary assignment operators (i.e., it offers members of the form tt(operator@=)), then the matching binary operators can all be implemented identically. The em(move-aware) tt(Class &operator@(Class &&lhs, Class const &rhs)) is easily implemented in terms of tt(operator@=) (note that the class itself doesn't have to be `move-aware' to define this function). The move-aware binary operator one requires a one line implementation, and as its implementation never changes it could safely be defined tt(inline): verb( Class operator@(Class &&lhs, Class const &rhs) { return std::move(lhs @= rhs); } ) The traditional binary operator can be implemented using its standard form: verb( Class operator@(Class const &lhs, Class const &rhs) { Class tmp(lhs); tmp @= rhs; return tmp; } ) The implementation in tt(bobcat/binops) is slightly more complex as it allows from lhs or rhs promotions. As the binary operators can all be implemented alike their definitions are perfectly suited for templates: A class offering a particular tt(operator@=) then automatically also offers the matching binary operators after including tt(bobcat/binops). Since the binary function templates are not instantiated until used their definitions can be processed by the compiler even if a class implements only a subset of the available binary assignment operators. manpagesection(NAMESPACE) The binary operator functions templates in tt(bobcat/binops) are em(not) implemented in a particular namespace. This allows sources to include tt(bobcat/binops) in multiple namespaces. If tt(bobcat/binops) is to be used in multiple namespaces then the include safeguard (using the identifier tt(INCLUDED_BOBCAT_BINOPS_)) must be suppressed between inclusions of tt(bobcat/binops) in different namespaces. E.g., to make the binary operator function templates available in a source file using the tt(namespace FBB) and in a source file using the default namespace the following scheme can be used: verb( #include // ensure std::move is available #include // required by binops namespace MY_NAMESPACE { #include // binary operators available in MY_NAMESPACE } #undef INCLUDED_BOBCAT_BINOPS_ // suppress the include guard #include // read binops again so the binary // operators can be used in the // default namespace as well ) manpagesection(INHERITS FROM) - manpagesection(OVERLOADED OPERATORS) The function templates in tt(bobcat/binops) implement all arithmetic binary operators, both move-aware and the traditional binary operators, expecting constant lvalue references. They can be used if the matching binary assignment operators were implemented in the classes for which the templates must be instantiated. The following operators are available: Move-aware operators, using temporary objects for its left-hand side operands: itemization( itb(Class operator*(Class &&lhs, Class const &rhs)) itb(Class operator/(Class &&lhs, Class const &rhs)) itb(Class operator%(Class &&lhs, Class const &rhs)) itb(Class operator+(Class &&lhs, Class const &rhs)) itb(Class operator-(Class &&lhs, Class const &rhs)) itb(Class operator<<(Class &&lhs, Class const &rhs)) itb(Class operator>>(Class &&lhs, Class const &rhs)) itb(Class operator&(Class &&lhs, Class const &rhs)) itb(Class operator|(Class &&lhs, Class const &rhs)) itb(Class operator^(Class &&lhs, Class const &rhs)) ) `Traditional' operators, using lvalue references to constant objects for its left-hand side operands: itemization( itb(Class operator*(Class const &lhs, Class const &rhs)) itb(Class operator/(Class const &lhs, Class const &rhs)) itb(Class operator%(Class const &lhs, Class const &rhs)) itb(Class operator+(Class const &lhs, Class const &rhs)) itb(Class operator-(Class const &lhs, Class const &rhs)) itb(Class operator<<(Class const &lhs, Class const &rhs)) itb(Class operator>>(Class const &lhs, Class const &rhs)) itb(Class operator&(Class const &lhs, Class const &rhs)) itb(Class operator|(Class const &lhs, Class const &rhs)) itb(Class operator^(Class const &lhs, Class const &rhs)) ) The latter group of operators also support promotions. manpagesection(EXAMPLE) verbinclude(../../binops/driver/driver.cc) manpagefiles() em(bobcat/binops) - defines the binary operator function templates manpageseealso() bf(bobcat)(7) manpagebugs() itemization( it() The header files tt(utility), defining tt(std::move), and tt(bobcat/typetrait) are required by, but are not included by tt(bobcat/binops). This was a design decision, see the bf(NAMESPACE) section. ) includefile(include/trailer) bobcat-3.19.01/documentation/man/table.yo0000644000175000017500000002373712235456275017216 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Table)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Table-formatter) manpagename(FBB::Table)(Generates row- or column-wise filled tables) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::Table) objects can be used to create tables. The tables are filled either column-wise or row-wise. Many of the table's characteristics may be fine-tuned using a separate bf(FBB::TableSupport) object, described in a separate man-page (bf(TableSupport)(3bobcat)). When no bf(FBB::TableSupport) object is used, a plain row-wise or column-wise table is constructed which can be inserted into a bf(std::ostream). Tables defined by tt(Table) consist of a (number of element dependent) number of rows and a fixed number of columns, the latter value is specified at construction time. Columns and rows are normally addressed using index values (starting at 0). Before the leftmost column, between the columns and beyond the last column em(separators) are defined. By default the separators are empty, but each separator may be given a (fixed) width or content. The separator before column tt(col) is addressed as separator tt(col), the rightmost separator is addressed as separator tt(nColummns). Likewise, rows can be separated from each other using separators. These separating rows are also empty by default. The row-separator before row tt(row) is addressed as row-separator tt(row). The row-separator following the final row is addressed as row-separator tt(nRows), where tt(nRows) is the value returned by the tt(nRows) member function. Non-default (i.e., non-empty) separators are defined using tt(FBB::TableSupport) objects (cf. bf(tablesupport)(3bobcat)). tt(Table) objects look a lot like tt(ostream) objects, but they also adopt a fairly rigid way to define new elements: each new insertion defines another table element, and it is difficult to end a row before it has received its tt(nColumn) number of elements. tt(Table)'s sister-class, tt(TableBuf), is a tt(std::streambuf) type of class, offering additional control through the use of a wrapping tt(ostream) class object. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::ostringstream) - tt(Table) inherits from bf(std::ostringstream), allowing insertions into a bf(Table) object. Each separate insertion adds another element to the bf(Table) object. bf(FBB::TableBase) - This class implements common elements of the table implementation (the tt(FBB::TableBuf) class is also derived from tt(TableBase). The tt(TableBase) class is not intended to be used otherwise, and no separate man-page is provided. All facilities provided by tt(Table) inherited from tt(TableBase) are described in this man-page. manpagesection(ENUMERATIONS) The following enumerations are defined by the class bf(FBB::Table): bf(enum FillDirection)nl() This enumeration defines two values: itemization( itb(ROWWISE) When this value is specified at construction time, elements are added row-wise to the table. I.e., the second element inserted into the bf(Table) will be found in the second column of the first row. itb(COLUMNWISE) When this value is specified at construction time, elements are added column-wise to the table. I.e., the second element will be found in the second row of the first column. ) bf(enum WidthType)nl() This enumeration defines two values: itemization( itb(COLUMNWIDTH) This value may be specified when the columns should be allowed variable widths. In this case each column will be as wide as its widest element. This is the default bf(WidthType) used by bf(Table) objects. itb(EQUALWIDTH) This value may be specified when all the table's columns should have equal width (i.e., equal to the width of the widest table element), ) manpagesection(CONSTRUCTORS) itemization( itb(Table(size_t nColumns, Table::FillDirection direction, Table::WidthType widthType = Table::COLUMNWIDTH)) The table's number of columns, the fill directions and the column width-type must be provided. The number of rows is implied by the combination of this parameter and the number of elements that is actually inserted into the bf(Table) object. The bf(direction) parameter specifies the way new elements are added to the bf(Table) object: row-wise or column-wise. Finally, the tt(widthType) parameter is used to specify the way the width of the table's columns is determined. Each column either defines its own width or all columns have equal widths. itb(Table(TableSupport &tableSupport, size_t nColumns, Table::FillDirection direction, Table::WidthType widthType = Table::COLUMNWIDTH)) This constructor operates identically to the previous constructor, but expects an additional reference to a bf(TableSupport) object. A bf(TableSupport) object offers additional formatting features used by the table defining elements like horizontal lines between rows, additional separators, etc, etc. The bf(TableSupport) object is passed as a non-const reference as the bf(Table) object must be able to manipulate its data. See bf(tablesuppport)(3bobcat) for more information about tt(TableSupport). ) The copy constructor is not available. manpagesection(OVERLOADED OPERATORS) itemization( itb(std::ostream &operator<<(std::ostream &str, Table &table)) This operator inserts a bf(Table) into a tt(std::ostream) object. This operator requires a non-const table as it may have to complete the table by adding empty elements (i.e., empty strings) to obtain a completely filled rectangular table. itb(Table &operator<<(Table &obj, Align const &align)) This operator is used to change the default alignment of either a column or an element. It is a wrapper around the member tt(setAlign()) (see below for its description). By default, all elements are right-aligned. See bf(align)(3bobcat) for more information about the tt(Align) class. itb(Table &operator<<(Table &obj, Type const &x)) This overloaded operator is defined as a function template: bf(Type) is a template type parameter instantiated to a type for which bf(std::ostringstream) insertions are possible. It inserts the value/object tt(x) into the bf(Table)'s bf(std::ostringstream) base class object as the next element of the table. ) The overloaded assignment operator is not available. manpagesection(MEMBER FUNCTIONS) itemization( itb(Table &append(std::string const &text char const *sep = " \t", bool addEmpty = false)) Fields in tt(text) separated by one of the characters in tt(sep) are added as additional elements to the bf(Table) object. Empty fields are ignored unless the parameter tt(addEmpty) is initialized to tt(true). itb(void clear()) The contents of the table are erased. All existing elements are removed, and the table will be empty. itb(void clearStr()) The contents of its tt(std::ostringstream) base class buffer are erased. itb(void fill(InputIterator begin, InputIterator end)) This member is defined as a member template; tt(InputIterator) is a template type parameter representing any input iterator. It can also be, e.g., a pointer to an insertable type. The iterators must point to data elements which can be inserted into an tt(std::ostream). The range of values implied by the member's iterator pair are inserted into the table as new elements. itb(void push_back(std::string const &element)) New elements can be added to the table using tt(push_back). It is, e.g., called from a tt(back_inserter) adaptor). itb(size_t nRows()) The currently available number of rows in the table is returned. Its value is only defined after calling bf(CHAR(d)ef()). itb(Table &setAlign(Align const &align)) The alignment type of either a column or an element of the bf(Table) object is defined using tt(setAlign). The standard alignments tt(std::left, std::right) and tt(std::internal) may be specified, but in addition the alignment tt(FBB::center) may be used if elements should be centered into their column. A construction like verb(tab << Align(2, FBB::center)) requests centering of all elements in the table's column having index value 2 (i.e., the table's 3rd column), whereas a construction like verb(tab << Align(2, 3, FBB::center)) requests centering of element [2][3]. It is the responsibility of the programmer to ensure that such elements exist. By default, all elements are right-aligned. itb(Table &CHAR(d)ef()) After inserting elements into a tt(Table) object its number of elements may or may not be an integral multiple of the number of columns specified at construction time. To `complete' a bf(Table) object to a rectangular object, for which all column widths and alignments have been determined tt(def) may be called. It is automatically called by tt(operator<<(ostream, Table)). In other situations it may be called explicitly to force the insertion of another row in a table using tt(ROWWISE) insertions. With tt(COLUMNWISE) insertions its working is complex, since new elements added to a tt(COLUMNWISE) filled table will reshuffle its elements over the table's columns. ) manpagesection(MANPULATORS) itemization( itb(Table &CHAR(d)ef(Table &table)) This manipulator can be inserted into a table to call the table's bf(CHAR(d)ef()) member. ) manpagesection(EXAMPLE) verbinclude(../../table/driver/driver.cc) manpagefiles() em(bobcat/table) - defines the class interface;nl() manpageseealso() bf(bobcat)(7), bf(align)(3bobcat), bf(manipulator)(3bobcat), bf(tablebuf)(3bobcat), bf(tablelines)(3bobcat), bf(tablesupport)(3bobcat) manpagebugs() Note that tt(CHAR(d)ef()) will reshuffle elements over the table's columns when new elements are added to the table subsequent to calling tt(CHAR(d)ef()) includefile(include/trailer) bobcat-3.19.01/documentation/man/cmdfinder.yo0000644000175000017500000002122312222576535020044 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::CmdFinder)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Command-function associations) manpagename(FBB::CmdFinder) (Determine (member) function associated with a command) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() Objects of the class bf(CmdFinder) determine which (member) function to call given a command. Although associations between commands and (member) functions are often defined in a switch, a switch is not the preferred way to define these associations because of the fect that the maintainability and clarity of switches suffer for even moderately large command sets. Moreover, the switch is hardly ever self-supporting, since usually some command-processing is required to determine command/bf(case)-value associations. The alternative (and preferred) approach, which is also taken by bf(CmdFinder) is to define an array of pointers to (member) functions, and to define the associations between commands and member functions as a mapping of commands to array indices. Plain associations between (textual) commands and functions to be called can also easily be defined using a bf(std::map) or other hash-type data structure. However, the syntactical requirements for such a bf(std::map) structure are non-trivial, and besides: user-entered commands often require some preprocessing before a command can be used as an index in a bf(std::map). The class bf(CmdFinder) is an attempt to offer a versatile implementation of associations between commands and (member) functions. In particular, the class offers the following features: itemization( it() Associations between textual commands and (member) functions are defined in a simple array of pairs: the first element defining a command, the second element containing the address of the function associated with the command. The function addresses may either be addresses of free or static member functions or they may be defined as member function addresses. it() Commands may be used `as-is', or the first word in a bf(std::string) may be used as the command; it() Commands may be specified case sensitively or case insensitively; it() Commands may have to be specified in full, or unique abbreviations of the commands may be accepted; it() Several types are defined by the class bf(CmdFinder), further simplifying the deriviation of classes from bf(CmdFinder). ) The class bf(CmdFinder) itself is defined as a template class. This template class should be used as a base class of a user-defined derived class defining the array of command-function associations. The class bf(CmdFinder) itself is a derived class of the class bf(CmdFinderBase), defining some template-independent functionality that is used by bf(CmdFinder). The enumeration and member functions sections below also contain the members that are available to classes derived from bf(CmdFinder), but which are actually defined in the class bf(CmdFinderBase). includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::CmdFinderBase) manpagesection(ENUMERATION) The enumeration bf(Mode) is defined in the class bf(CmdFinderBase). It contains the following values, which may be combined by the bf(bit_or) operator to specify the bf(CmdFinder) object's required mode of operation: itemization( itb(USE_FIRST) This value can be specified when the first word (any white-space separated series of characters) of a provided textual command should be used as the command to find. Both the command that is used and any trailing information that may be present can be obtained from the bf(CmdFinder) object. By default, the complete contents of the a provided command is used. itb(UNIQUE) This value can be specified when any unique abbreviation of a command may be accepted. Assuming that the commands tt(help) and tt(version) are defined, then the following (non-exhaustive) series are all accepted as specifications of the tt(help) command if bf(UNIQUE) is specified: tt(h, he, el, p). By default the command must match a command-key as found in the array of command-function associations exactly. itb(INSENSITIVE) When this value is specified, commands may be specified disregarding letter-casing. E.g., when bf(INSENSITIVE) is specified, both tt(Help) and tt(HELP) are recognized as tt(help). By default, letter casing is obeyed. ) So, by default a full, literal match between provided command and predefined command-keys is required. manpagesection(TEMPLATE TYPE PARAMETER) The template class bf(CmdFinder) has one template type parameter, which is the prototype of the functions defined in the array of command-function associations. This type becomes available as the typename bf(FunctionPtr) (defined by the class bf(CmdFinder) in the class that is derived from bf(CmdFinder)). manpagesection(PROTECTED DEFINED TYPES) The following (bf(protected)) types are defined by the template class bf(CmdFinder): itemization( itb(FunctionPtr) This type represents a pointer to the functions whose addresses are stored in the array of command-function associations. itb(Entry) This type represents the type bf(std::pair). Its em(first) field is the name of a command, its em(second) field is the function address associated with the command name. ) manpagesection(CONSTRUCTORS) itemization( itb(CmdFinder(Entry const *begin, Entry const *end, size_t mode = 0)) This constructor is defined in the bf(protected) section of the bf(CmdFinder) class. Its parameters tt(begin) and tt(end) define the half-open range of bf(Entry) objects, defining the associations between commands and functions. The parameter tt(begin) should be initialized to the first element of an array of bf(Entry) objects, the parameter tt(end) must point just beyond the last element of the array. The parameter tt(mode) may be speified using any combination of values of the bf(Mode) enumeration, using the bf(bit_or) operator to combine multiple values. When a non-supported value is specified for tt(mode), an bf(FBB::Exception) exception is thrown. itb(Note) There is no default constructor. ) Copy and move constructors are available. manpagesection(OVERLOADED OPERATORS) The copy and move assignment operators are available. manpagesection(PUBLIC MEMBER FUNCTION) itemization( itb(setMode(size_t mode)) This member function (defined in the class bf(CmdFinderBase)) may be called to redefine the mode of the bf(CmdFinder) object. The tt(mode) parameter should be initialized subject to the same restrictions as mentioned with the bf(CmdFinder)'s constructor. ) manpagesection(PROTECTED MEMBER FUNCTIONS) itemization( itb(std::string const &beyond() const) This member function returns the text that may have been entered beyond the command (if bf(Mode) value bf(USE_FIRST) was specified). It is empty if no text beyond the command was encountered. It is initially empty, and will be redefined at each call of bf(findCmd()) (see below). itb(std::string const &cmd() const) This member returns the original (untransformed) command as encountered by the bf(CmdFinder) object. It is initially empty, and will be redefined at each call of bf(findCmd()) (see below). object. itb(size_t count() const) This member function returns the number of commands matching the command that is passed to the function bf(findCmd()) (see below). Its return value is 0 when bf(findCmd()) hasn't been called yet and is updated at each new call of bf(findCmd()). itb(FunctionPtr findCmd(std::string const &cmd)) Regarding the bf(CmdFinder) object's bf(mode) setting, this function returns the address of the function to call given the provided command. By default, if no match was found, the address of the function stored in the last element of the array of command-function associations is returned (i.e, element tt(end[-1])). ) manpagesection(PROTECTED DATA MEMBERS) The class bf(CmdFinder) has access to some protected data members of the class bf(CmdFinderBase), which should not be used or modified by classes derived from bf(CmdFinder). manpagesection(EXAMPLE) verbinclude(../../cmdfinder/driver/driver.cc) manpagefiles() em(bobcat/cmdfinder) - defines the class interface+nl() em(bobcat/cmdfinderbase) - defines the base class of bf(CmdFinder). manpageseealso() bf(bobcat)(7), bf(cmdfinderbase)(3bobcat), bf(errno)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/serversocket.yo0000644000175000017500000001520512222576535020633 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::ServerSocket)(3bobcat) (_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Server Socket) manpagename(FBB::ServerSocket) (Server socket accepting Internet connection requests) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() An bf(FBB::ServerSocket) may be constructed to listen for connection requests from the Internet or from the local host. Connection requests may be accepted in either em(blocking) or em(non-blocking) modes. When a connection is accepted a socket is returned which may be used to read information from or write information to the client that requested the connection. The socket that is made available is a em(file descriptor) which may be used to initialize a bf(std::istream) and/or bf(std::ostream). The bf(std::istream) is used to read information from the client process; the bf(std::ostream) is used to send information to the client process. Since a socket may be considered a em(file descriptor) the avaiable bf(FBB::IFdStream), bf(FBB::IFdStreamBuf), bf(FBB::OFdStream), and bf(FBB::OFdStreamBuf) classes may be used profitably here. Note that having available a socket does not mean that this defines the communication protocol. It is (still) the responsibility of the programmer to comply with an existing protocol or to implement a tailor-made protocol. The latter situation implies that the sequence of input- and output operations is defined by the programmer. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::SocketBase) manpagesection(CONSTRUCTOR) itemization( itb(ServerSocket(size_t port)) This constructor initializes an bf(FBB::ServerSocket) object, which will listen for connections at the specified port. The construction of the socket does not mean that the bf(FBB::ServerSocket) object is actually listening for connections. To start listening, the member bf(listen()) should be used. ) The copy constructor is not available. manpagesection(MEMBER FUNCTIONS) All members of bf(FBB::SocketBase) (and thus of bf(FBB::InetAddress)) are available, as bf(FBB::ServerSocket) inherits from bf(FBB::SocketBase). itemization( itb(void listen(size_t backlog = 5, bool blocking = true)) The bf(listen()) member defines the way the bf(FBB::ServerSocket) will listen for clients requesting a connection. It can be used only once with a bf(FBB::ServerSocket). An bf(FBB::Exception) object is thrown if listening fails, if the constructor could not create a socket, or if the bf(SocketBase) base class could not properly be constructed. The bf(listen()) member's tt(backlog) parameter defines the size of the bf(FBB::ServerSocket)'s internal queue in which connection requests may be stored waiting for their turn to be serviced. When tt(backlog) requests are waiting and another request arrives, then that request is lost. The member's second parameter, tt(blocking), is used to control the blocking mode. By default, blocking is used, and tt(listen()) will wait until a connection is established. This is ok in situations where clients connect infrquently and for relatively short time intervals. Otherwise, in more complex programs, an bf(FBB::Selector) object can be used to sense input on the server socket and/or on various client sockets. itb(SocketBase accept()) The bf(accept()) member returns an bf(FBB::SocketBase) object containing information about the client whose connection request was accepted. The bf(FBB::SocketBase) object's socket value may be used to initialize streams that can be used to communicate with the client. In more complex programs the bf(FBB::SocketBase) could be passed to a class derived from bf(FBB::Fork), handling the communication with the child as a separate (child) process. ) manpagesection(EXAMPLE) See also the bf(clientsocket)(3bobcat) example. verb( #include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) { cerr << "Provide server port number\n"; return 1; } size_t portnr = A2x(argv[1]); ServerSocket server(portnr); cerr << "server listens on port " << argv[1] << endl; cerr << "serversocket returns:\n" << "address = " << server.dottedDecimalAddress() << "\n" "port = " << server.port() << endl; int fd = server.socket(); // open the socket's descriptor cout << "File descriptor of the socket is " << fd << "\n" "The server terminates when it receives a " "single `q' on a line\n" "A connection is terminated when no input " "is received anymore.\n" "Then another connection is possible" << endl; server.listen(); // listen in blocking mode while (true) { SocketBase fdb = server.accept(); int fd = fdb.socket(); cerr << "Client FD = " << fd << ", " << endl << "address = " << fdb.dottedDecimalAddress() << ", " << endl << "communication through port " << fdb.port() << endl; IFdStream in(fd); // stream to read from client OFdStream out(fd); // stream to write to client string cmd; while (getline(in, cmd)) { cout << "Got: " << cmd << endl; out << "Got: " << cmd << "\r" << endl; if (cmd[0] == 'q') return 0; } cout << "Ready for another connection\n"; } } catch (Exception const &err) { cerr << err.what() << endl << "Server socket on port " << argv[1] << " can't be opened" << endl; return -1; } ) manpagefiles() em(bobcat/serversocket) - defines the class interface manpageseealso() bf(bobcat)(7), bf(clientsocket)(3bobcat), bf(fork)(3bobcat), bf(ifdstream)(3bobcat), bf(ifdstreambuf)(3bobcat), bf(inetaddress)(3bobcat), bf(localserversocket)(3bobcat), bf(ofdstream)(3bobcat), bf(ofdstream)(3bobcat), bf(select)(2), bf(selector)(3bobcat), bf(socketbase)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/configfile.yo0000644000175000017500000003541012222576535020221 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::ConfigFileile)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz)(Configuration File Processing) manpagename(FBB::ConfigFileile) (A class processing standard unix-like configuration files) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(ConfigFile) objects read standard tt(unix)-style configuration files. Lines are stored with initial white-space (blanks and tabs) removed. If a line ends in \, then the next line (initial white-space removed) is appended to the current line. If the tt(rmComment) flag is set to tt(true) blanks lines and information on lines from the first tt(#) are removed. If the comment character (tt(#)) is prefixed by a backslash (i.e., tt(\#)) it is not considered comment, but replaced by a single tt(#) character. Likewise, if the tt(rmComment) flag was set two consecutive backslash characters are replaced by a single backslash character, In the retrieved configuration information it appears as a single tt(#) character. If the configuration file should contain tt(\#) write tt(\\#), this results in replacing tt(\#) by tt(#), leaving tt(\#). All non-empty lines of the configuration file (when comment is ignored comment is not considered to be line-content) are stored in the bf(ConfigFile) object. When line indices should be stored the (0-based) line indices of lines are available as well. At construction time comment handling (keep comment / remove comment), case-sensitive searching (sensitive / insensitive) and index storage (store / don't store) can be specified. It can't be modified using the tt(open) member, but overloaded assignment is supported and comment and letter case handling can be modified by set-members. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ENUMERATIONS) The following enumerations are defined by the class bf(ConfigFile): itemization( itb(Comment) This enumeration has two values: nl() bf(ConfigFile::KeepComment) is used to indicate that comment on lines must be kept; nl() bf(ConfigFile::RemoveComment) is used to indicate that comment on lines must be removed; itb(SearchCasing) This enumeration also has two values:nl() bf(ConfigFile::SearchCaseSensitive) is used to do case sensitive searches for targets;nl() bf(ConfigFile::SearchCaseInsensitive) is used to do case insensitive searches for targets. itb(Indices) This enumeration also has two values:nl() bf(ConfigFile::IgnoreIndices) when used, the line numbers of the original configuration file are not available;nl() bf(ConfigFile::StoreIndices) when used, the line numbers of the original configuration file are also available;nl() ) manpagesection(TYPES) The following types are defined by the class tt(ConfigFile): itemization( itb(const_iterator) a tt(const_iterator) is an iterator pointing to a line (tt(std::string)) of the configuration file; itb(const_RE_iterator) a tt(const_RE_iterator) is an iterator pointing to lines matching a regular expression. It supports the following operations: itemization( itt(const_RE_iterator &operator++()): the prefix increment operator increments the iterator to point to the next line in the configuration file matching the iterator's regular expression; itt(std::string const &operator*()): the dereferencing operator returns the line of the configuration file the iterator refers to; itt(std::string const *operator->()): the pointer operator returns the address of the line of the configuration file the iterator refers to; ) tt(const_RE_iterator)s can be compared for (in)equality and they can be copy-constructed; tt(const_RE_iterator) objects are returned by the tt(ConfigFile::beginRE), tt(ConfigFile::endRE) and tt(ConfigFile::beginEndRE) members and cannot otherwise be constructed. When two tt(const_RE_iterator) objects are subtracted the number of lines matching their regular expression is returned. E.g., (see below for a description of the functions used in the next example): verb( ConfigFile cf(...) auto iters = cf.beginEndRE("^hello"); cout << "There are " << (iters.second - iters.first) << " lines starting with hello\n"; ) The two tt(const_RE_iterator) objects should refer to the same regular expression. The provided example illustrates how this is realized using tt(beginEndRE). tt(FBB::Pattern) is used to perform the regular expression pattern matching. ) manpagesection(CONSTRUCTORS) itemization( itb(ConfigFile(Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices)) This constructor is used to create an empty bf(ConfigFile) object. It is not associated with an input stream: the tt(open) member can be used for that. The parameters can be used to specify specific handling of comment, letter-casing and storage of line numbers in the original configuration file. itb(ConfigFile(std::string const &fname, Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices)) This constructor is used to create a bf(ConfigFile) object, which is filled with the information from a file whose name is provided as the constructor's first argument. The other parameters are used as described with the first constructor. It throws an tt(FBB::Exception) exception if the file could not be opened. )nl() The copy and move constructors are available. manpagesection(OVERLOADED OPERATORS) itemization( itb(std::string const &operator[](size_t idx) const) This member returns the (0-based) tt(idx)-th line of the configuration file. )nl() The overloaded assignment and move assignment operators are available. manpagesection(MEMBER FUNCTIONS) itemization( itb(ConfigFile::const_iterator begin() const) This member returns a tt(const_iterator) to the first line of the configuration file. itb(ConfigFile::const_iterator end() const) This member returns a tt(const_iterator) pointing beyond the last line of the configuration file. itb(std::pair beginEndRE(std::string const &target) const) A pair of tt(const_RE_iterators) is returned. The tt(first) field of the pair is a tt(const) iterator to the first element (i.e., line) of the bf(ConfigFile) object in which the regular expression tt(target) is found. The tt(second) field is a tt(const) iterator marking the end of the series of lines started at the the first line matching the regular expression specified by tt(target). If the tt(RemoveComment) flag was specified, then comment-text is not searched. The iterator returned in the pair's tt(first) field can be incremented until the iteratr returned in the pair's tt(second) field is reached; all iterators (unequal the iterator in tt(second)) point to lines matching the specified regular expression. The iterator's increment operator searches the next line matching the specified regular expression. Although the difference between two tt(const_RE_iterators) can be computed it is a relatively expensive operation. The difference is obtained by performing repeated regular expression matchings rather than the mere algebraic subtraction of pointer values. If the difference cannot be computed tt(std::numeric_limits::max()) is returned. This member also interprets the tt(SearchCasing) flag. itb(std::pair beginEndRE() const) A pair of tt(const_RE_iterators) is returned, both marking the end of a regular expression search. itb(ConfigFile::const_iterator find(std::string const &target) const) This member returns an iterator to the first element (i.e., line) of the tt(FBB::ConfigFile) object in which tt(target) is found. Note that tt(target) may appear anywhere within a line. If the tt(RemoveComment) flag was specified, then comment-text is not searched. Use the tt(end) member to determine the end-iterator. It is not guaranteed that all lines between the returned iterator and tt(end) contain tt(target). This member also interprets the tt(SearchCasing) flag. itb(std::string findKey(std::string const &keyPattern, size_t count = 1) const) This member can be used to retrieve information from lines having the general pattern `tt(keyPattern value)'. Initial and trailing white space on lines are ignored. tt(keyPattern) itself should not contain initial or trailing white space. At least one white space character must appear between tt(keyPattern) and tt(value). If at least tt(count) lines were found matching tt(keyPattern value) then this member returns the first sequence of non white space characters following tt(keyPattern) after matching tt(count) lines matching tt(keyPattern value) (i.e., `tt(value)' is returned). If tt(value) is empty or if fewer than tt(count) lines match tt(keyPattern) an empty string is returned. An tt(FBB::Exception) exception is thrown if tt(count) equals 0. itb(std::string findKeyTail(std::string const &keyPattern, size_t count = 1) const) This member can be used to retrieve information from lines having the general pattern `tt(keyPattern value)', merely followed by white space. Initial and trailing white space on lines are ignored. tt(keyPattern) itself should not contain initial or trailing white space. At least one white space character must appear between tt(keyPattern) and tt(value). If at least tt(count) lines were found matching tt(keyPattern value) then this member returns the information beyond tt(keyPattern) after matching tt(count) lines matching tt(keyPattern) (i.e., `tt(value)' is returned). This function differs from tt(findKey) in that all information trailing tt(keyPattern) is returned in tt(value). If tt(value) is empty or if fewer than tt(count) lines match tt(keyPattern) an empty string is returned. An tt(FBB::Exception) exception is thrown if tt(count) equals 0. itb(ConfigFile::const_iterator findRE(std::string const &target) const) This member returns an iterator to the first line of the bf(ConfigFile) object matching the regular expression tt(target). After calling this function tt(beginEndRE) returns an iterator pair whose tt(first) field is an iterator to the same line and whose tt(second) field is the end-iterator for lines matching tt(target). If the tt(RemoveComment) flag was specified, then comment-text is not searched. The inherited tt(end) member can be used to determine the end-iterator. It is not guaranteed that all lines between the returned iterator and tt(end) also contain tt(target). If that is required, the members tt(beginRE) and tt(endRE) can be used. This member also interprets the tt(SearchCasing) flag. itb(size_t index(size_t idx)) This function should only be used when the parameter tt(StoreIndices) was specified at construction time. In that case it returns the original 0-based line index in the configuration file associated with the tt(idx)sups(th) (0-based) index in the current tt(Configuration) object. itb(size_t index(const_iterator const &iter)) This function should only be used when the parameter tt(StoreIndices) was specified at construction time. In that case it returns the original 0-based line index in the configuration file associated with the configuration line in the current tt(Configuration) object pointed to by tt(iter). This may also be an (incremented version of the) iterator returned by the member tt(findRE) or tt(beginRE), as long as the iterator's value is within the half open range tt(beginRE) to tt(endRE). itb(void open(std::string const &fname)) This member reads the configuration file having name tt(fname). It redefines the current contents of the bf(ConfigFile) object, destroying any information previously stored in it. The configuation file is read according to the latest setting of the comment-flag. It throws an tt(FBB::Exception) exception if the file cannot be opened. This member clears previously available information and reinitializes the object with information read from the new file. itb(void setCommentHandling(Comment type)) This member can be used to change the comment-handling type originally set by the constructor, or set by earlier calls of this function. When called it won't affect the current contents of the bf(ConfigFile) object, but new calls of its tt(open) member reads the configuation file according to the last setting of the comment flag. itb(void setSearchCasing(SearchCasing type)) This member can be used to change the handling of the letter-casing originally set by the constructor, or set by earlier calls of this function. When called it won't affect the current contents of the bf(ConfigFile) object, but new calls of its tt(open) member reads the configuation file according to the last setting of the letter-casing flag. itb(size_t size() const) This member returns the number of lines in the configuration file. ) manpagesection(EXAMPLE) Assume the configuration file is called tt(config.rc) and contains the following lines: COMMENT(Keep the blank following the backslashes below:) verb( # this is ignored noline: this one too line: this is found this is not a line containing line: at the beginning \ of the line line: this one is line: what about this one? \ it's extending over multiple lines and there may, of course, be more lines in this file ) The following program may be compiled and run as tt(a.out config.rc): verb( #include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { ConfigFile cf(argv[1]); cout << *cf.find("this one") << endl; // find text within a line // find all lines matching // `^line:' copy(cf.beginRE("^line:"), cf.endRE(), ostream_iterator(cout, "\n")); } ) Producing the output: verb( noline: this one too line: this is found line: this one is line: what about this one? it's extending over multiple lines ) manpagefiles() em(bobcat/configfile) - defines the class interface manpageseealso() bf(argconfig)(3bobcat), bf(bobcat)(7), bf(errno)(3bobcat), bf(pattern)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/exception.yo0000644000175000017500000001407412222576535020115 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Exception)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Error handler) manpagename(FBB::Exception)(std::exception objects acception stream insertions) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::Exception) objects derived from tt(std::exception), but accept stream insertions. Their intended use consists of throwing an anonymous object, into which the text of the tt(std::exception::what) message has been inserted. tt(Exception) exceptions are thrown by several Bobcat classes. These classes are tt( Arg, ArgConfig, BigInt, Cgi, Cidr, ClientSocket, CmdFinderBase, ConfigFile, DateTime, DecryptBuf, DigestBuf, EncryptBuf, Fork, GetHostent, Glob, HMacBuf, Hostname, LocalClientSocket, LocalServerSocket, LocalSocketBase, Log, MailHeaders, Mbuf, Milter, Mstream, OFoldStreambuf, OneKey, Pattern, Pipe, Process, Redirector, Selector, ServerSocket, Signal, SocketBase, Stat, TempStream, User, Xpointer) manpagesection(NAMESPACE) bf(FBB)nl() All constructors, members, operators and manipulators, mentioned in this man-page, are defined in the namespace bf(FBB). manpagesection(INHERITS FROM) bf(std::exception) manpagesection(ENUMERATION) The enumeration tt(Protection) is used by the member tt(protection) described below. The enumeration has two values: itemization( itt(ANY): an existing file may have any set of protection bits; itt(EQUAL): an existing file mut have exactly the set of protection bits as specified when calling tt(Exception::protection). ) manpagesection(CONSTRUCTORS) itemization( itb(Exception()) The default constructor itb(Exception(int errnoValue)) This constructor stores the provided tt(errnoValue) value in the global tt(::errno) variable, provided by the run-time support system. ) Move and copy constructors are available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::exception) are available, as bf(FBB::Exception) inherits from this class. itemization( itb(char const *what() const noexcept(true) override) Returns the text that was inserted into the bf(FBB::Exception) object. ) manpagesection(OVERLOADED OPERATORS) itemization( itb(Exception &&operator<<(Exception &&in, Type const &t)) A function template implementing the overloaded insertion operator. It can be used to insert values of any type that can also be inserted into an tt(ostringstream) object. ) The overloaded assignment and move assignment operators are available. manpagesection(STATIC MEMBERS) The following convenience functions can be used for controlled opening of stream-type objects, like tt(std::ofstream) and tt(std::ifstream). These stream-type objects must support tt(open) and tt(close) members, like those provided by tt(std::ifstream) and tt(std::ofstream). If the stream was already open it is first closed. If opening fails an tt(FBB::Exception) exception is thrown containing a short message stating that the named stream could not be opened. itemization( itb(static void open(StreamType &stream, std::string const &name)) Opens the stream object, using its default tt(open) member. itb(static void open(int errnoValue, StreamType &stream, std::string const &name)) Opens the stream object, using its default tt(open) member. If opening the stream fails, then the thrown bf(FBB::Exception) assigns tt(errnoValue) to tt(::errno). itb(static void open(StreamType &stream, std::string const &name, std::ios::openmode mode)) Opens the stream object, using its tt(open) member, passing tt(mode) to tt(open). itb(static void open(int errnoValue, StreamType &stream, std::string const &name, std::ios::openmode mode)) Opens the stream object, using its tt(open) member, passing tt(mode) to tt(open). If opening the stream fails, then the thrown bf(FBB::Exception) assigns tt(errnoValue) to tt(::errno). itb(static size_t protection(std::string const &path, size_t protect, Protection type = EQUAL)) Returns the protection bits (cf. bf(open)(2)) of tt(path). The tt(protect) parameter is used to specify the requested protection bits. This value is usually specified as an octal value. If the specified value exceeds 0777 an exception is thrown. The third parameter is only used in combination with already existing files. If specified as tt(ANY) the file's actual permission bits are not compared with tt(protect); if specified as tt(EQUAL) the file's permission bits must be identical to tt(protect), or an exception is thrown. If tt(path) does not yet exist a file tt(path) with permission tt(protect) is created. This member returns tt(path)'s permission bits. If tt(path) is created by tt(protection), then opening a stream for tt(path) does not change tt(path)'s protection. ) manpagesection(MANIPULATOR) The following manipulator (which is em(not) part of the bf(FBB::Exception), class, but em(is) defined in the bf(FBB) namespace) can be inserted into the bf(FBB::Exception) object: itemization( itb(FBB::errnodescr) The descriptive text associated with the current tt(errno) value is inserted into the bf(FBB::Exception) object (it can also be used to insert the descriptive text in a tt(std::ostream) object). No text is inserted if tt(errno) equals zero. This manipulator is thread-safe (but tt(errno) may be modified when tt(errno) holds an invalid value). ) manpagesection(EXAMPLE) verb( if (exceptionalCondition) throw FBB::Exception(1) << "Exceptional condition occurred"; ) manpagefiles() em(bobcat/exception) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/arg.yo0000644000175000017500000003052212222576535016664 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Arg)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Command Line Arguments) manpagename(FBB::Arg)(A singleton class interfacing command line arguments) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() Singleton class (see Gamma em(et al.), 1995) built around bf(getopt())(3) and bf(getopt_long())(3). The class handles short- and long command-line options, includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ENUMERATION) The bf(FBB::Arg::Type) enumeration is defined by the bf(FBB::Arg) class. It has the following values intended for public use: bf(None, Required, Optional). These values are used when constructing objects of the nested class bf(FBB::Arg::LongOption), see below. manpagesection(CONSTRUCTORS) Since the class is a em(Singleton), no public constructors are available. Instead, static members are offered to initialize and access the single bf(FBB::Arg) object. See below. manpagesection(STATIC MEMBERS) itemization( itb(FBB::Arg &initialize(char const *optstring, int argc, char **argv)) Initializes the bf(FBB::Arg) singleton. Must be called only once. Throws an bf(FBB::Exception) exception if called repeatedly or if called with tt(argv) not containing a defined option (which is shown by the bf(FBB::Exception)'s tt(what()) member). Returns a reference to the singleton object, allowing code initializing bf(Arg) to use the initialized object immediately. itb(FBB::Arg &initialize(char const *optstring, LongOption const * const begin, LongOption const * const end, int argc, char **argv)) Initializes the bf(FBB::Arg) singleton. Accepts two iterators of an array of bf(Arg::LongOption) objects, holding long-options. Must be called only once. Throws an bf(FBB::Exception) exception if called repeatedly or if called with tt(argv) not containing a defined option (which is shown by the bf(FBB::Exception)'s tt(what()) member). See the description of bf(Arg::LongOption) below. Returns a reference to the singleton object, allowing code initializing bf(Arg) to use the initialized object immediately. tt(optstring) should consist of letters, possibly postfixed by: itemization( it() a colon (tt(:)), indicating that the option has a required argument; it() a double colon (tt(::)), indicating that the option itself has an optional argument (in that case, the option's value will be empty, unless specified). ) itb(FBB::Arg &instance()) Returns the instance of the bf(Arg) object, available after calling one of the bf(Arg::initialize()) members. If called before initialization, an tt(FBB::Exception) exception is thrown. ) manpagesection(OVERLOADED OPERATOR) itemization( itb(char const *operator[](size_t idx) const) Returns tt(argument[idx]), after having removed all specified options. 0 is returned if no tt(arg[x]) is available. The program name (tt(argv[0])) is NOT counted here: index 0 refers to the first ARGUMENT, e.g., the program's tt(argv[1]). ) manpagesection(NON-STATIC MEMBER FUNCTIONS) itemization( itb(char const **argPointers()) Returns tt(argv)-like set of pointers to all remaining arguments. The last element is guaranteed to be a 0-pointer. The first tt(nArg()) elements point to the respective bf(C)-string values of the arguments. itb(std::string const &basename() const) Returns the program's basename. itb(size_t beyondDashes() const) Returns the index of the first argument after a tt(--) argument or tt(nArgs()) if no tt(--) argument was encountered.nl() A tt(--) argument ends tt(Arg)'s argument processing, and all arguments beyond the first tt(--) argument are kept `as is'. The tt(beyondDashes) member returns the index of the first argument beyond the tt(--) argument, which itself is removed from the remaining set of arguments. itb(size_t nArgs() const) Returns the number of arguments left after option-removal. The program name bf(argv[0]) is NOT counted here. itb(size_t nLongOptions() const) Returns the number of long options for which no short option synonym exist. If long options are multiply specified, then each specification is counted. itb(size_t nOptions() const) Returns the number of specified single character options. If short options have long option synonyms, then these long option synonyms are counted as if they were specified as single character options. If single character options (or their long option synonyms) are multiply specified, then each specification is counted. itb(size_t option(int option) const) The number of times `option' (or its long option synonym, if defined) was specified is returned. itb(size_t option(std::string const &options) const) The number of times one of the options specified in the `option' argument (or their long option synonyms) were present is returned. itb(size_t option(string *value, int option) const) Returns the number of times the provided option (or its long option synonym) was present. If the return value is non-zero then the value of the first occurrence of this option is stored in tt(*value), which is left untouched if `option' was not present. 0 may be specified for bf(value) if the option does not have a value or if the value should not be stored. itb(size_t option(size_t idx, string *value, int option) const) Returns the number of times the provided option (or its long option synonym) was present. If the return value is non-zero then the value of the tt(idx)th occurrence (0-based offset) of this option is stored in tt(*value), which is left untouched if `option' was not present or if tt(idx) is or exceeds the number of specifications of the provided option. 0 may be specified for bf(value) if the option does not have a value or if the value should not be stored. itb(size_t option(size_t *idx, string *value, int option) const) Returns the number of times the provided option (or its long option synonym) was present. If the return value is non-zero then the offset (within the series of tt(option) specifications) of the first option having a non-empty option value is returned in tt(*idx), while its option value is stored in tt(*value). Both tt(*value) and tt(*idx) are left untouched if `option' was not present. 0 may be specified for bf(value) if the option does not have a value or if the value should not be stored. itb(size_t option(string *value, char const *longOption) const) Returns the number of times the specified long option (not having a single-character synonym) was present. Its value is then stored in tt(*value), which is left untouched if the long option was not present. 0 may be specified for bf(value) if the option does not have a value or if the value should not be stored. itb(size_t option(size_t idx, string *value, char const * longOption) const) Returns the number of times the provided long option (not having a single-character synonym) was present. If the return value is non-zero then the value of the tt(idx)th occurrence (0-based offset) of this long option is stored in tt(*value), which is left untouched if the long option was not present or if tt(idx) is or exceeds the number of specifications of the provided long option. 0 may be specified for bf(value) if the long option does not have a value or if the value should not be stored. itb(size_t option(size_t *idx, string *value, int longOption) const) Returns the number of times the provided long option (not having a single-character synonym) was present. If the return value is non-zero then the offset (within the series of this long option specifications) of the first long option having a non-empty option value is returned in tt(*idx), while its option value is stored in tt(*value). Both tt(*value) and tt(*idx) are left untouched if long option was not present. 0 may be specified for bf(value) if the long option does not have a value or if the value should not be stored. itb(void versionHelp(void (*usage)(std::string const &progname), char const *version, size_t minArgs, int helpFlag = 'h', int versionFlag = 'v') const) If tt(versionFlag) was specified, and the tt(helpFlag) was not specified the program's name (using bf(basename())) and tt(version) is displayed to tt(std::cout). Otherwise, if the tt(helpFlag) was provided or if there are fewer arguments than tt(minArgs) tt(usage()) is called with argument bf(basename()). If either version- or help information is shown, the bf(int) value 1 is thrown as an exception.nl() Note that tt(versionhelp) compares tt(minArgs) against tt(nArgs). If tt(minArgs) should be compaired against the number of arguments up to a possible `--' argument (i.e., tt(beyondDashes)' return value), then add tt(nArgs() - beyondDashes()) to the tt(minArg) argument. E.g., verb( arg.versionHelp(usage, version, 2 + arg.nArgs() - arg.beyondDashes()); ) The address of the tt(usage()) function, the current version and the minimum number of arguments must be specified. Default argument values are provided for the option flags. ) manpagesection(THE NESTED CLASS FBB::Arg::LongOption) Long options are defined using objects of the nested class bf(FBB::Arg::LongOption). This class offers the following constructors: itemization( itb(FBB::Arg::LongOption(char const *name, FBB::Arg::Type type = None)) This constructor is used to define a long option for which no corresponding short option is defined. The parameter tt(name) is the name of the long option (without prefixing the tt(--) characters, which em(are) required when specifying the long option). itb(FBB::Arg::LongOption(char const *name, int optionChar)) This constructor is used to define a long option for which a corresponding short option is defined. The parameter tt(name) is the name of the long option (without prefixing the tt(--) characters, which em(are) required when specifying the long option). ) In a program, long options may be specified as follows: itemization( it() First, construct an array verb( FBB::Arg::LongOption longOptions[] = { c1, c2, ... cn } ) Where tt(c1, c2, ..., cn) are bf(n) constructor invocations of bf(FBB::Arg::LongOption()) constructors it() Next, pass bf(longOptions, LongOptions + n) as 2nd and 3rd arguments to bf(initialize()) ) manpagesection(EXAMPLE) The following example illustrates defining long options and shows an initialization. It is not a full-fledched example in the sense of a small runnable program. verb( #include using namespace FBB; namespace // the anonymous namespace can be used here { Arg::LongOption longOptions[] = { Arg::LongOption("debug"), Arg::LongOption("filenames", 'f'), Arg::LongOption("help", 'h'), Arg::LongOption("version", 'v'), }; auto longEnd = longOptions + sizeof(longOptions) / sizeof(longOptions[0]); } int main(int argc, char **argv) try { Arg &arg = Arg::initialize("df:hv", longOptions, longEnd, argc, argv); // code using arg, etc. } catch(Exception const &err) // handle exceptions { cerr << err.what() << endl; return err.which(); } catch(int x) { return x; } ) manpagefiles() em(bobcat/arg) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/log.yo0000644000175000017500000002110312222576535016667 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Log)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Log messages) manpagename(FBB::Log)(bf(std::ostream) handling log messages) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() The class bf(FBB::Log) is a tt(std::ostream) initialized with a tt(FBB::LogBuffer). It is used to send log-messages to the (r)syslog stream. Refer to the bf(logbuffer)(3bobcat) man-page for details about this process. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::ostream) manpagesection(ENUMERATIONS) The enumeration bf(TimeStamps) is defined in the namespace bf(FBB), primarily for initializing bf(FBB::LogBuffer) objects. It is used with bf(FBB::Log) members as well. It has the following values: itemization( itb(NOTIMESTAMPS) Log-messages will not have timestamps prepended to them. itb(TIMESTAMPS) Log-messages will have timestamps prepended to them. ) The enumeration bf(LogManipulator) is used to handle special or exceptional situations through manipulators. It is defined in the namespace bf(FBB) and has the following two values: itemization( itb(FATAL) This value may be inserted into an bf(FBB::Log) object to throw an bf(FBB::Exception) exception (see bf(operator<<()) below); itb(nl) This value may be inserted into an bf(FBB::Log) object to terminate the current line. It will em(not) cause the next line to begin with a time stamp (if applicable) and the current em(message level) cannot be modified using a bf(level)(3bobcat) manipulator. It is used to allow a single log message to occupy multiple textual lines. itb(endl) This is the standard tt(ostream) manipulator. When inserted into a bf(Log) object the current buffer is flushed. Note that flushing does not happen immediately when a newline (tt(\n)) is inserted into the log stream. Alternatively, tt(std::flush) may be inserted into the bf(Log) object to flush its buffer. ) manpagesection(CONSTRUCTORS) itemization( itb(Log(char const *delim = " ")) The default constructor creates a bf(FBB::Log) object which isn't yet associated with a stream to log messages on. The member bf(open()) (see below) may be used to define such a stream. By default, all messages will have a time stamp prepended to them (see the description of the member bf(setTimestamp()) below). The parameter bf(delim) is inserted immediately beyond the time stamp. If a delimiter is inappropriate, an empty string or a 0-pointer may be specified. itb(Log(std::ostream &out, char const *delim = " ")) This constructor creates a bf(FBB::Log) object logging its messages to the provided tt(std::ostream) object. By default, all messages will have a time stamp prepended to them (see the description of the member bf(setTimestamp()) below). The parameter bf(delim) is inserted immediately beyond the time stamp. If a delimiter is inappropriate, an empty string or a 0-pointer may be specified. itb(FBB::Log(std::string const &filename, std::ios::openmode mode = std::ios::out | std::ios::app, char const *delim = " ")) This constructor creates a bf(FBB::Log) object logging its messages to the named file. If tt(filename == "&1") the logmessages will be written to the standard output stream. If tt(filename == "&2") the logmessages will be written to the standard error stream. By default the file is created if not existing, and all messages are appended to the stream. By default, all messages will have a time stamp prepended to them (see the description of the member bf(setTimestamp()) below). The parameter bf(delim) is inserted immediately beyond the time stamp. If a delimiter is inappropriate, an empty string or a 0-pointer may be specified. ) The copy constructor is not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::ostream) are available, as bf(FBB::Log) inherits from this class. itemization( itb(size_t level()) This member returns the currently set log level (i.e., the value set at the latest tt(setLevel()) call). itb(std::ostream &level(size_t useLevel)) This member defines a log-level. Messages will be inserted into the stream when tt(useLevel) is equal to or exceeds the level set by bf(setLevel()). The maximum level which can be selected is bf(std::numeric_limits::max()). If not even such messages should be inserted into the bf(ostream), then the stream should be deactivated, using bf(off()), see below. The selected level remains active until redefined. Alternatively, the bf(FBB::level) manipulator may be inserted into an (empty) bf(FBB::Log) object (see bf(level)(3bobcat)). itb(void off()) Prevents any log messages from being generated. It may be cancelled by bf(setLevel()) (see below). itb(void open(std::string const &filename, std::ios::openmode mode = std::ios::out | std::ios::app, char const *delim = " ")) This member (re)associates an bf(FBB::Log) object with the named file. If tt(filename == "&1") the logmessages will be written to the standard output stream. If tt(filename == "&2") the logmessages will be written to the standard error stream. By default the file is created if not existing, and all messages are appended to the stream. By default, all messages will have a time stamp prepended to them (see the description of the member bf(setTimestamp()) below). The parameter bf(delim) is inserted immediately beyond the time stamp. If a delimiter is inappropriate, an empty string or a 0-pointer may be specified. itb(void setLevel(size_t newLevel)) Redefines the internal message level. Messages having at least level tt(newLevel) will be written. If the member is used without explicit argument, logging is suspended. itb(void setTimestamp(FBB::TimeStamps stamp, char const *delim = " ")) The member function (de)activates time stamp prepending. Use the value bf(FBB::TIMESTAMPS) to prepend time stamps, bf(FBB::NOTIMESTAMPS) suppresses time stamps. A timestamp consists of the month, the day number of the month and the (local) time of the current message, as usually appearing in messages in tt(/var/log) files. E.g., tt(Aug 5 13:52:23). The parameter bf(delim) is inserted immediately beyond the time stamp. If a delimiter is inappropriate, an empty string or a 0-pointer may be specified. When bf(stamps == FBB::NOTIMESTAMPS delim) is ignored. ) manpagesection(STATIC MEMBERS) itemization( itb(FBB::Log &initialize(std::string const &filename, std::ios::openmode mode = std::ios::out | std::ios::app, char const *delim = " ")) Returns a reference to a static bf(FBB::Log) object. It may only be called once, or an tt(FBB::Exception) exception is thrown. It associates a static bf(FBB::Log) object with the named file. If tt(filename == "&1") the logmessages will be written to the standard output stream. If tt(filename == "&2") the logmessages will be written to the standard error stream. By default the file is created if not existing, and all messages are appended to the stream. By default, all messages will have a time stamp prepended to them (see the description of the member bf(setTimestamp()) below). The parameter bf(delim) is inserted immediately beyond the time stamp. If a delimiter is inappropriate, an empty string or a 0-pointer may be specified. itb(FBB::Log &instance()) Returns a reference to a static bf(FBB::Log) object, available after calling bf(Log::initialize()). If called before tt(Log::initialize()) an tt(FBB::Exception) exception is thrown. ) manpagesection(OVERLOADED OPERATOR) The following overloaded operator is defined outside of the bf(FBB) namespace. It may be used to insert an bf(FBB::LogManipulator) into an bf(FBB::Log) object. If the overloaded operator is used in combination with another type of object it performs no actions. itemization( itb(std::ostream &::operator<<(std::ostream &str, FBB::LogManipulator)) When inserting bf(FBB::FATAL) an bf(FBB::Exception) exception is thrown; when inserting bf(FBB::nl) the line is terminated, but next insertions will not start with a time stamp (if applicable). ) manpagesection(EXAMPLE) verbinclude(../../log/driver/driver.cc) manpagefiles() em(bobcat/log) - defines the class interface manpageseealso() bf(bobcat)(7), bf(errno)(3bobcat), bf(level)(3bobcat), bf(logbuffer)(3bobcat) manpagebugs() None reported includefile(include/trailer) bobcat-3.19.01/documentation/man/mlm.yo0000644000175000017500000000472212222576535016703 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::mlm)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (OFoldStream manipulator) manpagename(FBB::mlm)(Manipulator modifying left margins of OFoldStream objects) manpagesynopsis() bf(#include ) or nl() bf(#include ) nl() Linking option: tt(-lbobcat) manpagedescription() The tt(mlm) class implements a manipulator that can be inserted into tt(OFoldStream) objects to modify the stream's left margin by a requested amount. The request cannot result in a negative left margin value. If a negative left margin would be the arithmetic result of the request then left margin 0 will silently be used. Depending on the tab-setting of the tt(OFoldStream) the inserted value represents the number of blank space characters or the number of tab-characters that will be added to the left margin. The request will be processed at the next newline character or tt(std::flush) or tt(std::endl) manipulator that is inserted into the stream. If a line is still empty once an tt(mlm) object and a tt(flush) manipulator are inserted into the stream then the new left margin will be effective at the next word inserted into that line (cf., the example section below) A em(bad_cast) exception is thrown when the manipulator is inserted into an tt(ostream) that is not using a tt(OFoldStreambuf) buffer. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTOR) itemization( itb(mlm(int addValue)) ) The standard copy constructor is available. manpagesection(MEMBER FUNCTIONS) There are no public or protected member functions in this class. manpagesection(EXAMPLE) verb( #include #include using namespace std; using namespace FBB; int main() { OFoldStream out(cout, 0, 80); out << "hello world (left margin is 0)" << mlm(4) << "\n" "this uses a 4 character wide left margin\n" << mlm(-10) << flush << "left margin -6 changed to 0, active on this line\n"; return 0; } ) manpagefiles() em(bobcat/mlm) - defines the class interface manpageseealso() bf(bobcat)(7), bf(manipulators)(3bobcat), bf(lm)(3bobcat), bf(ofoldstream)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/argconfig.yo0000644000175000017500000002644512222576535020063 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::ArgConfig)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Program Arguments) manpagename(FBB::ArgConfig)(A singleton class processing program arguments) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() Singleton class (see Gamma em(et al.), 1995) built around bf(getopt)(3) and bf(getopt_long)(3). The class handles short- and long command-line options as well as configuration files. In addition to the standard command-line options, configuration files containing long options as their keys, optionally followed by a colon are also recognized by the various tt(option) members. E.g., an option tt(--input filename) can be specified in the configuration file like verb( input: filename ) or verb( input filename ) Options without arguments should probably not use the colon, although it is accepted by tt(ConfigArg). E.g., for the option tt(--verbose) both forms are OK: verb( verbose verbose: ) includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::Arg),nl() bf(FBB::ConfigFile) manpagesection(CONSTRUCTORS) Since the class is a em(Singleton), no public constructors are available. Instead, static members are offered to initialize and access the single bf(ArgConfig) object. See below. manpagesection(STATIC MEMBERS) itemization( itb(FBB::ArgConfig &initialize(char const *optstring, int argc, char **argv, [std::string const &fname,] Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices)) Initializes the bf(FBB::ArgConfig) singleton. Must be called only once. Throws an bf(FBB::Exception) exception if called repeatedly or if called with tt(argv) not containing a defined option (which is shown by the bf(FBB::Exception)'s tt(what) member). The tt(fname) argument is optional. If provided, a configuration file by the specified name is opened (and must exist); if omitted the tt(ArgConfig) is created without using a configuration file. In the latter case a configuration file may be specified later using the tt(open) member inherited from tt(ConfigFile). The final three parameters are tt(ConfigFile) parameters, receiving the shown default values. This constructor returns a reference to the singleton object, allowing code initializing bf(ArgConfig) to use the initialized object immediately. itb(FBB::ArgConfig &initialize(char const *optstring, LongOption const * const begin, LongOption const * const end, int argc, char **argv, [std::string const &fname,] Comment cType = KeepComment, SearchCasing sType = SearchCaseSensitive, Indices iType = IgnoreIndices)) Initializes the bf(FBB::ArgConfig) singleton. Accepts two iterators of an array of bf(Arg::LongOption) objects, holding long-options. Must be called only once. Throws an bf(FBB::Exception) exception if called repeatedly or if called with tt(argv) not containing a defined option (which is shown by the bf(FBB::Exception)'s tt(what) member). Refer to bf(arg)(3bobcat) for the description of bf(Arg::LongOption). The constructor's final six parameters are identical to the previous constructor's final six arguments. This constructor returns a reference to the singleton object, allowing code initializing bf(ArgConfig) to use the initialized object immediately. The argument tt(optstring) should consist of letters, possibly postfixed by: itemization( it() a colon (tt(:)), indicating that the option has a required argument; it() a double colon (tt(::)), indicating that the option itself has an optional argument (in that case, the option's value will be empty, unless specified). ) itb(FBB::ArgConfig &instance()) Returns the instance of the bf(ArgConfig) object, available after calling one of the bf(ArgConfig::initialize) members. If called before initialization, an tt(FBB::Exception) exception is thrown. ) manpagesection(NON-STATIC MEMBER FUNCTIONS) All public members of the tt(Arg) and tt(ConfigFile) classes are also offered by the tt(ArgConfig) class. As several tt(option) members were reimplemented by this class all tt(option) members are discussed below. All other members inherit straight from the classes tt(Arg) and tt(ConfigFile). Consult their man pages for details. itemization( itb(size_t option(int option) const) Returns the number of times `option' (or its long option synonym, if defined) was specified as command line option or as as a configuration file option. itb(size_t option(std::string const &options) const) Returns the total number of times any of the characters specified in the `options' string (or their long option synonyms) was specified as command line option or as as a configuration file option. itb(size_t option(string *value, int option) const) Returns the number of times the provided option (or its long option synonym) was present as either a command line option or as a configuration file option. If the return value is non-zero then the value of the first occurrence of this option (first checking the command line options; then checking the configuration file) is stored in tt(*value), which is left untouched if `option' was not present. 0 may be specified for bf(value) if the option does not have a value or if the value should not be stored. itb(size_t option(size_t idx, string *value, int option) const) This member acts identically to the tt(Arg::option) member having the identical prototype. It does not consider the configuration file but merely returns the number of times the provided option (or its long option synonym) was present. If the return value is non-zero then the value of the tt(idx)th occurrence (0-based offset) of this option is stored in tt(*value), which is left untouched if `option' was not present or if tt(idx) is or exceeds the number of specifications of the provided option. 0 may be specified for bf(value) if the option does not have a value or if the value should not be stored. itb(size_t option(size_t *idx, string *value, int option) const) This member acts identically to the tt(Arg::option) member having the identical prototype. It does not consider the configuration file but merely returns the number of times the provided option (or its long option synonym) was present. If the return value is non-zero then the offset (within the series of tt(option) specifications) of the first option having a non-empty option value is returned in tt(*idx), while its option value is stored in tt(*value). Both tt(*value) and tt(*idx) are left untouched if `option' was not present. 0 may be specified for bf(value) if the option does not have a value or if the value should not be stored. itb(size_t option(string *value, char const *longOption) const) Returns the number of times the specified long option (not having a single-character synonym) was present as either a command line option or in the configuration file. If found, then the value found at the first occurrence of the option (first considering the command line options, then the configuration file) is stored in tt(*value). The string pointed to by tt(value) is left untouched if the long option was not present. 0 may be specified for bf(value) if the option does not have a value or if the value should not be stored. itb(size_t option(size_t idx, string *value, char const * longOption) const) This member acts identically to the tt(Arg::option) member having the identical prototype. It does not consider the configuration file but merely returns the number of times the provided long option (not having a single-character synonym) was present. If the return value is non-zero then the value of the tt(idx)th occurrence (0-based offset) of this long option is stored in tt(*value), which is left untouched if the long option was not present or if tt(idx) is or exceeds the number of specifications of the provided long option. 0 may be specified for bf(value) if the long option does not have a value or if the value should not be stored. itb(size_t option(size_t *idx, string *value, int longOption) const) This member acts identically to the tt(Arg::option) member having the identical prototype. It does not consider the configuration file but merely returns the number of times the provided long option (not having a single-character synonym) was present. If the return value is non-zero then the offset (within the series of this long option specifications) of the first long option having a non-empty option value is returned in tt(*idx), while its option value is stored in tt(*value). Both tt(*value) and tt(*idx) are left untouched if long option was not present. 0 may be specified for bf(value) if the long option does not have a value or if the value should not be stored. ) manpagesection(EXAMPLE) verb( #include #include #include #include using namespace std; using namespace FBB; ArgConfig::LongOption lo[] = { ArgConfig::LongOption("option", 'o'), ArgConfig::LongOption("value-option", 'v') }; class X { ArgConfig &d_arg; public: X(); void function(); }; X::X() : d_arg(ArgConfig::instance()) {} void X::function() { if (d_arg.nArgs() == 0) throw Exception() << "Provide the name of a config file as 1st arg"; cout << "Counting " << d_arg.option('o') << " instances of -o or " "--option\n"; d_arg.open(d_arg[0]); // Now open the config file explicitly // (alternatively: use a constructor expecting // a file name) cout << "Counting " << d_arg.option('o') << " instances of -o or " "--option\n"; string optval; size_t count = d_arg.option(&optval, 'v'); cout << "Counting " << count << " instances of -v or --value-option\n"; if (count) cout << "Option value = " << optval << endl; } int main(int argc, char **argv) try { ArgConfig::initialize("ov:", lo, lo + 2, argc, argv); X x; x.function(); return 0; } catch (Exception const &err) { cout << "Terminating " << err.what() << endl; return 1; } ) manpagefiles() em(bobcat/argconfig) - defines the class interface manpageseealso() bf(arg)(3bobcat), bf(configfile)(3obcat), bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/redirector.yo0000644000175000017500000002101512257021365020244 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Redirector)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (System Level File Redirection) manpagename(FBB::Redirector)(Redirects a file descriptor to another descriptor) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() Objects of the class bf(FBB::Redirector) set up a system level file redirection, using file descriptors rather than streams. tt(Redirector) objects are effectively em(wrappers) around the bf(dup2)(2) system call. System level redirection allows the programmer to send output to, e.g., the standard output stream, which actually appears at another stream (e.g., the standard error). tt(Redirector) objects are used to redirect the output sent to a stream having file descriptor tt(x) to another stream having file descriptor tt(y), much like the shell's tt(>) operator redirects the standard output to some file. tt(Redirector) objects can also be used to extract the information from a stream having file descriptor tt(x) in fact from another stream having file descriptor tt(y), much like the shell's tt(<) operator is used to read the information in some file from the standard input. Redirection using tt(Redirector) objects represents a stronger form of redirection than redirection offered by bf(C++) itself, which uses tt(std::streambuf) redirection, and which is, because of that, bound to the program's scope. System level redirection, on the other hand, is applied at the system level, allowing the programmer to redirect standard streams when starting a program. For example, the standard error is commonly written to the standard output using an invocation like tt(program 2>&1). When constructing tt(Redirector) objects a file descriptor is required. The file descriptor specified at the constructor is the file descriptor that is used by the program to read information from or to write information to. Another file descriptor is required to set up the redirection: the file descriptor used here is the file descriptor of the stream that actually holds the information which is extracted from the file descriptor that was passed to the tt(Redirector)'s constructor; or it is the file descriptor of the stream receiving the information which is written to the stream having the file descriptor that was passed to the tt(Redirector)'s constructor. When a tt(Redirector) object goes out of scope, its file descriptor are left as-is. In particular, note that no bf(close)(2) operation is performed on the tt(Redirector's) file descriptors. After setting up redirection using the tt(Redirector's) member functions and passing the tt(Redirector's) file descriptors to code that uses the tt(Redirector's) descriptors, the tt(Redirector) object could in fact safely be destroyed. Formally, file descriptors are not defined in bf(C++), but they are available in many types of operating systems. In those systems each `file' has an associated `file descriptor'. A file descriptor is an bf(int), which is an index into the program's file allocation table, maintained by the system. Another type of well-known entities which are file descriptors are em(sockets). Well-known filedescriptors (defined in, e.g., tt(unistd.h)) having fixed values are itemization( tt() 0 (tt(STDIN_FILENO)), representing the standard input stream (tt(std::cin)); tt() 1, (tt(STDOUT_FILENO)), representing the standard output stream (tt(std::cout)); tt() 2, (tt(STDERR_FILENO)), representing the standard error stream (tt(cerr)); ) Notes: itemization( it() System-level redirections are kept during system calls of the bf(exec)(3) family. it() Destroying a tt(Redirector) object does em(not) undo the redirection set up by that object. ) includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ENUM) The enumeration bf(StandardFileno) holds the following values: itemization( itt(STDIN) (0) itt(STDOUT) (1) itt(STDERR) (2) ) These values may be used to set up a redirection instead of the plain numbers. manpagesection(CONSTRUCTORS) itemization( itb(Redirector(int fd)) This constructor expects the file descriptor of the file that will be used by the program to access (read, write) another file. The file descriptor that is passed to the constructor is used by the program, and will often be tt(STDIN, STDOUT), or tt(STDERR), allowing the program to use tt(cin, cout), or tt(cerr) to extract information from, or insert information into other streams using its standard input and output streams. ) The copy constructor is available. manpagesection(MEMBER FUNCTIONS) itemization( itb(void swallow(int otherFd) const) This member function expects a file descriptor which should become a synonym of the constructor's file descriptor. The constructor's file descriptor is redirected to tt(otherFd). After successfully calling tt(swallow) information written to tt(otherFd) is in fact written to the constructor's file descriptor. E.g., if the constructor's file descriptor represents a file on disk and tt(otherFd) is tt(STDOUT_FILENO) then all information sent to the standard output stream is actually sent to the file on disk: verb( information sent to otherFd -> is received at the constructor's Fd (e.g., otherFd = STDOUT_FILENO) ) Conversely, if the constructor's file descriptor represents a file on disk and tt(otherFd) is tt(STDIN_FILENO) then all information extracted from the standard input stream is actually read from the file on disk. verb( information extracted from otherFd <- is read from the constructor's Fd (e.g., otherFd = STDIN_FILENO) ) Following tt(swallow) both file descriptors are open, and refer to the constructor's file descriptor. Before setting up the redirection, the original tt(otherFd) is closed by bf(close)(2). Following tt(swallow) both file descriptors can be used, and refer to the constructor's file descriptor. If after calling tt(swallow) bf(close)(2) is called for one of them, then the other one remains open. If redirection fails an bf(FBB::Exception) object is thrown, whose tt(which()) member shows the system's tt(errno) value set by the failing bf(dup2)(2) function. itb(void through(int otherFd) const) This member function expects a file descriptor which should become a synonym of the constructor's file descriptor. The constructor's file descriptor is redirected to tt(otherFd). The constructor's file descriptor can no longer be used, as it is closed by bf(close)(2). After successfully calling tt(through) information written to tt(otherFd) is in fact written to the constructor's file descriptor. E.g., if the constructor's file descriptor represents a file on disk and tt(otherFd) is tt(STDOUT_FILENO) then all information sent to the standard output stream is actually sent to the file on disk: verb( information sent to otherFd -> is received at the constructor's Fd (e.g., otherFd = STDOUT_FILENO) ) Conversely, if the constructor's file descriptor represents a file on disk and tt(otherFd) is tt(STDIN_FILENO) then all information extracted from the standard input stream is actually read from the file on disk. verb( information extracted from otherFd <- is read from the constructor's Fd (e.g., otherFd = STDIN_FILENO) ) Before setting up the redirection, the original tt(otherFd) is closed by bf(close)(2). Following tt(through) only tt(otherFd) can be used, and it refers to (i.e., reads or writes) the constructor's file descriptor. If redirection fails an bf(FBB::Exception) object is thrown, whose tt(which()) member shows the system's tt(errno) value set by the failing bf(dup2)(2) function. ) manpagesection(EXAMPLE) verb( #include #include using namespace std; using namespace FBB; int main() { Redirector redirector(Redirector::STDOUT); redirector.swallow(Redirector::STDERR); cerr << "This appears at the standard output stream\n" "use `a.out > /dev/null' to suppress this message" << endl; } ) manpagefiles() em(bobcat/redirector) - defines the class interface manpageseealso() bf(bobcat)(7), bf(errno)(3bobcat), bf(dup2)(2), bf(execl)(3) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/ofoldstreambuf.yo0000644000175000017500000002175412222576535021136 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::OFoldStreambuf)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz)(Fold long lines) manpagename(FBB::OFoldStreambuf)(Folds long lines written to ostream) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::OFoldStreambuf) is a specialization of tt(FBB::OFilterStreambuf) folding long lines written to an tt(std::ostream) object. The tt(OFoldStreambuf) writes the (folded) lines to a second tt(ostream) (the em(destination stream) which is either used by or opened by the tt(OFoldStreambuf) object. Internally the tt(OFoldStreambuf) defines its actions using a little finite state automation distinguishing three states (INDENT, WS and NON_WS) and three character categories (tt(\n), other white space characters (space), and non-space characters). The nine combinations resulting from these two sets are discussed below. tt(OFoldStreambuf) objects will never fold lines in the middle of series of non-blank characters (called a `word' below) but will always break a line at a white space character. The resulting lines will always appear to the right of a configurable left margin and to the left of a configurable right margin. There is a somewhat pathological exception to this: if a word is too long to fit in between the margins then the word will exceed the right hand margin. The indentation used for the left margins is configurable to either blanks (the default) or tabs. When tabs are used the width of a tab character is configurable, using a default of 8 positions in the destination stream. What follows is a description of the em(Finite State Automaton) (FSA) defining what happens when various character types appear at its three states. The phrase `... is written' means that the described information is written to the tt(ostream) used or opened by the tt(OFoldStreambuf) object. tt(OFoldStreambuf)'s initial state is tt(INDENT): DEFINEMACRO(rw)(3)(row(cell(ARG1)cell(ARG2)cell(ARG3))) table(3)(lll)( rw(State)(char.)(description) rowline() rw(INDENT) (\n) (a new line character is written) rw() (space) (the indentation is set;) rw()()(the space character is added to the indentation;) rw()()(next state: WS) rw() (non-ws) (the character is added to the currently stored word;) rw()()(next state: NON_WS) rowline() rw(WS) (\n) (a new line character is written;) rw()()(stored white-space is erased;) rw()()(next state: INDENT) rw() (space) (white space character is added to the currently) rw()()(stored space characters;) rw() (non-ws) (the character is added to the currently stored word;) rw()()(next state: NON_WS) rowline() rw(NON_WS) (\n) (stored white space and word are written;) rw()()(a new line is written;) rw()()(next state: INDENT) rw() (space) (stored white space and word are written;) rw()()(white space character is added to the currently) rw()()(stored space characters;) rw()()(next state: WS) rw() (non-ws) (the character is added to the currently stored word;) rowline() ) includefile(include/namespace) manpagesection(INHERITS FROM) FBB::OFilterStreambuf manpagesection(ENUMERATION) The enumeration tt(TabsOrBlanks) is used to select tabs or blanks when writing the indentation. The default is blanks. When tabs are selected the display width of tabs characters can be configured as well (using the default of 8 positions for each tab-character. The enumeration has two values: itemization( itb(BLANKS) The default, indicating that the left margin is specified and written as a number of blanks; itb(TABS) Indicating that the left margin is specified and written as a number of tab-characters. ) The enumeration tt(TrailingBlanks) is used to configure the tt(OFoldStreambuf) object with respect to any trailing blanks that may appear on the final line. These trailing blanks can appear on the final line it it is not properly terminated with a newline character but instead ends in white space. By default these white space characters are ignored, but they may be kept as well. The enumeration has two values: itemization( itb(IGNORE_TRAILING_BLANKS) This indicates that trailing blanks appearing at the final line if it is not terminated by a newline should not be written to the destination tt(std::ostream). This is the default used by tt(OFoldStreambuf) objects. itb(KEEP_TRAILING_BLANKS) This indicates that trailing blanks at the final line if it is not terminated by a newline should be written to the destination tt(std::ostream) ) manpagesection(CONSTRUCTORS) itemization( itb(OFoldStreambuf(size_t leftIndent = 0, size_t rightMargin = 80, TabsOrBlanks tob = BLANKS, TrailingBlanks tb = IGNORE_TRAILING_BLANKS)) This constructor initializes an tt(OFoldStreambuf) object but does not associate it with a destination stream. It can also be used as the default constructor. itb(OFoldStreambuf(char const *fname, size_t leftIndent = 0, size_t rightMargin = 80, TabsOrBlanks tob = BLANKS, TrailingBlanks tb = IGNORE_TRAILING_BLANKS)) This constructor initializes an tt(OFoldStreambuf) object and opens (using tt(std::ios::out)) the destination stream using the name specified as its tt(fname) argument. itb(OFoldStreambuf(std::ostream &stream, size_t leftIndent = 0, size_t rightMargin = 80, TabsOrBlanks tob = BLANKS, TrailingBlanks tb = IGNORE_TRAILING_BLANKS)) This constructor initializes an tt(OFoldStreambuf) object and uses as its destination stream the tt(std::ostream stream). ) The destructor writes any buffered information to the destination stream and will then flush the destination stream. manpagesection(MEMBER FUNCTIONS) All members of bf(FBB::OFilterStreambuf), in particular its tt(out()) and tt(open()) members are available, as bf(FBB::OFoldStreambuf) inherits from this class. itemization( itb(void setMargins(size_t leftMargin, size_t rightMargin)) This member can be used to modify the left- and right folding margins. Note that the left margin may also be modified using the tt(FBB::lm) and tt(FBB::mlm) manipulators. itb(void setTrailingBlanks(TrailingBlanks tb)) This member can be used to modify the currently used tt(TrailingBlanks) parameter. itb(void useBlanks()) This member can be used to select blanks to be used when inserting left margins. itb(void useTabs(size_t tabWidth = 8)) This member can be used to select tab-characters to be used when inserting left margins. The second parameter is used to specify the display width of a tab-character. ) manpagesection(STATIC MEMBER FUNCTIONS) itemization( itb(size_t leftMargin(std::ostreambuf const *buffer)) This member returns the current left margin setting of the tt(OFoldStreambuf) object passed to it as its argument. The member defines a tt(std::streambuf) parameter which is down cast to an tt(OFoldStreambuf) and an tt(FBB::Exception) exception is thrown if that cast fails. itb(size_t rightMargin(std::ostreambuf const *buffer)) This member returns the current right margin setting of the tt(OFoldStreambuf) object passed to it as its argument. The member's parameter is down cast in the same way as tt(leftMargin())'s argument: an tt(FBB::Exception) exception is thrown if that cast fails. ) manpagesection(PROTECTED MEMBER FUNCTION) The member listed in this section implements the tasks of the comparably named virtual function in the class's private interface. This separates the redefinable interface from the user-interface. The class bf(OFoldStreambuf) can, in accordance with Liskov's Substitution Principle, be used as a tt(std:streambuf); but it also offers a facility for classes deriving from bf(OFoldStreambuf). This facility is listed here. itemization( itb(int pSync()) The contents of the bf(OFoldStreambuf)'s internal buffer is flushed. ) manpagesection(EXAMPLE) verb( #include #include #include #include using namespace std; using namespace FBB; int main() { OFoldStreambuf fb(cout, 4, 40); ostream out(&fb); out << lm(4); string line; while (getline(cin, line)) out << line << '\n'; return 0; } ) manpagefiles() em(bobcat/ofoldstreambuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(lm)(3bobcat), bf(mlm)(3bobcat), bf(ofilterstreambuf)(3bobcat), bf(ofoldstream)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/typetrait.yo0000644000175000017500000000624412222576536020145 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::TypeTrait)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Error handler) manpagename(FBB::TypeTrait)(shortdesc) manpagesynopsis() bf(#include )nl() manpagedescription() bf(FBB::TypeTrait) is a traits class. It does not define any member functions or data members, but merely types. It can be used to determine the basic type and other characteristics of (const) plain, (const) pointer or (const) reference types. It was designed after Alexandrescu's (2001) tt(TypeTraits) template class. The bf(FBB::LpromotesR) class template is used to determine, compile-time, whether its second (right-hand side) template type can be promoted to its first (left-hand side) template type. The bf(FBB::Use) class template expects two typenames tt(LHS) and tt(RHS) and defines tt(typename Use::type) as tt(LHS) if tt(RHS) can be promoted to tt(LHS) or it defines tt(typename Use::type) as tt(RHS). includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(TypeTrait) bf(TYPE) is the template type parameter whose characteristics must be determined. tt(TypeTrait) defines the type tt(Plain): the plain type (the type without const, pointer, reference type indication) of any const or non-const plain, pointer, lvalue- or rvalue-reference type. tt(TypeTrait) defines the following tt(bool) values: itemization( itt(isClass): tt(true) if the template type argument represents a class (struct) type, tt(false) otherwise. itt(isConst): tt(true) if the template type argument represents a const type, tt(false) otherwise. itt(isPointer): tt(true) if the template type argument represents a pointer type, tt(false) otherwise. itt(isR_Ref): tt(true) if the template type argument represents a rvalue reference type, tt(false) otherwise. itt(isRef): tt(true) if the template type argument represents an lvalue reference type, tt(false) otherwise. ) manpagesection(LpromotesR) tt(LpromotesR) defines the enum constant tt(yes) as 1 if an tt(RightType) argument can be promoted to tt(LeftType) value or object. The enum value tt(yes) is defined as 0 if no such constructor is available or if such a constructor is defined using the tt(explicit) keyword. manpagesection(EXAMPLES) Here is an example using tt(LpromotesR): verb( int main() { cout << "string promotes char const *: " << LpromotesR::yes << '\n'; // 1 cout << "string promotes string " << LpromotesR::yes << '\n'; // 1 cout << "char const * promotes string " << LpromotesR::yes << '\n'; // 0 } ) manpagefiles() em(bobcat/typetrait) - defines the class interface manpageseealso() bf(bobcat)(7)nl() Alexandrescu A. (2001) bf(Modern C++ Design), Addison-Wesley, Boston. manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/tempstream.yo0000644000175000017500000000420112222576536020270 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::TempStream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Temporary fstream) manpagename(FBB::TempStream)(Temporary fstream) manpagesynopsis() bf(#include )nl() manpagedescription() bf(FBB::TempStream) objects are temporary tt(std::fstreams) opened with mode 0600 (user only read+write). The file created by a tt(TempStream) object is removed from the file system once the tt(TempStream) object goes out of scope. A tt(TempStream) object creates an empty file, and information can immediately be inserted into the tt(TempStream) object. To switch between insertion and extraction simply call tt(seekg) (for extraction) or tt(seekp) (for insertion). includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::fstream) manpagesection(CONSTRUCTORS) itemization( itb(TempStream(std::string const &base = "/tmp/FBB::TempStream")) The constructor initializes the object and creates a file with the given base-name to which six random characters are appended. If the tt(TempStream) could not be constructed an tt(FBB::Exception) exception is thrown. ) The copy constructor is not available. manpagesection(MEMBER FUNCTIONS) All bf(std::fstream) members are available, as bf(FBB::TempStream) inherits from this class. In addition, tt(TempStream) itself offers itemization( itb(std::string const &fileName() const) The name of the created temporary file. ) manpagesection(EXAMPLE) verb( #include #include using namespace std; using namespace FBB; int main() { TempStream ts("/tmp/demo"); ts << "Hello world\n"; ts.seekg(0); string line; getline(ts, line); cout << line << ", removed: " << ts.fileName() << '\n'; } ) manpagefiles() em(bobcat/tempstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(mkostemp)(3) manpagebugs() None reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/bigint.yo0000644000175000017500000007605012224230675017367 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::BigInt)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Big Integers) manpagename(FBB::BigInt)(Arithmetic on Integers of Unlimited Size) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat -lcrypto) manpagedescription() This class is defined as a wrapper class around the em(openSSL) tt(BN) series of functions, offering members to perform arithmetic on integral values of unlimited sizes. Members are offered to generate primes and to perform all kinds of common arithmetic operations on tt(BigInt) objects. Also, conversions to characters and standard numerical value types are offered. Below, the phrase em(the object) may also refer to the object's value. The context in which this occurs will make clear that the object's value rather than the object as-is is referred to. Various constructors accept tt(BIGNUM) arguments. Type tt(BIGNUM) is the type containing an integer of unlimited precision as defined by OpenSSL. Signs of tt(BigInt) are handled in a special way. Whether a tt(BigInt) is negative or positive is determined by its sign-flag, and not by a sign bit as is the case with tt(int) typed values. Since tt(BigInt) values have unlimited precision shifting values to the left won't change their signs. Operators return either a reference to the current (modified) object or return a tt(BigInt) object containing the computed value. The rule followed here was to implement the operators analogously to the way the operators work on tt(int) type values and variables. E.g., tt(operator+()) returns a tt(BigInt) value whereas tt(operator+=()) returns a tt(BigInt &) reference. All members modifying their objects return a reference to the current (modified) object. All members not modifying the current object return a tt(BigInt) object. If both members exists performing the same functionality the name of the member returning a tt(BigInt) object ends in a tt(c) (const) (e.g., tt(addMod) and tt(addModc). Almost all operators, members and constructors (except for the default constructor) throw tt(Exception) exceptions on failure. manpagesection(INHERITS FROM) - manpagesection(TYPE) The class bf(BigInt) defines the type tt(Word), which is equal to the type tt(BN_ULONG) used by tt(OpenSSL) to store integral values of unlimited precision. A tt(Word) is an tt(unsigned long), which is, depending on the architecture, usually 64 or 32 bits long. manpagesection(ENUMERATIONS) bf(Msb)nl() This (most significant bit) enumeration is used when generating a cryptographically strong random number. Its values are: itemization( itb(MSB_UNKNOWN) The most significant bit may be 0 or 1. itb(MSB_IS_ONE) The most significant bit is guaranteed to be 1. itb(TOP_TWO_BITS_ONE) The two most significant bits are guaranteed to be 1, resulting in a product of two values each containing tt(nBits) having tt(2 * nBits) bits. ) bf(Lsb)nl() This (least significant bit) enumeration is used when generating random numbers, ensuring that the resulting value is either odd or even. itemization( itb(EVEN) The random value will be an even value; itb(ODD) The random value will be an odd value. ) manpagesection(CONSTRUCTORS) itemization( itb(BigInt()) The default constructor initializes a tt(BigInt) value to 0. itb(explicit BigInt(BIGNUM const &value)) This constructor initializes a tt(BigInt) from a tt(const BIGNUM). itb(explicit BigInt(BIGNUM const *value)) This constructor initializes a tt(BigInt) from a pointer to a tt(const BIGNUM). itb(BigInt(Type value)) This constructor is defined as a member template. Any type that can be converted using a static cast to an tt(unsigned long) can be used as argument to this constructor. Promotion is allowed, so in many situations where tt(BigInt)s are expected a plain numerical value can be used as well. itb(BigInt(char const *bigEndian, size_t length, bool negative = false)) This constructor initializes a tt(BigInt) from tt(length) big-endian encoded bytes stored in tt(bigEndian). This constructor interprets the tt(char) values pointed at by tt(bigEndian) as unsigned values. Use this constructor to reconstruct a tt(BigInt) object from the data made available by the tt(bigEndian) member. If the number represents a negative value, then provide a third argument tt(true). itb(explicit BigInt(std::string const &bigEndian, bool negative = false)) This constructor initializes a tt(BigInt) from the bytes stored in tt(bigEndian), which must be big-endian encoded. This constructor interprets the tt(char) values stored in tt(bigEndian) as unsigned values. If the number that is stored in tt(bigEndian) represents a negative value, then provide a second argument tt(true). ) The standard copy constructor is available, the move constructor is not available. manpagesection(MEMBER FUNCTIONS) itemization( itb(BigInt &addMod(BigInt const &rhs, BigInt const &mod) ) tt(Rhs) is added (modulo tt(mod)) to the current object. itb(BigInt addModc(BigInt const &rhs, BigInt const &mod) ) The sum (modulo tt(mod)) of the current object and tt(rhs) is returned. itb(BigInt::Word at(size_t index) const) Returns the tt(Word) at tt(index). E.g., on a 32 bit architecture, if the bf(BigInt) value equals 2+sups(33), then tt(at(0)) returns 0, and tt(at(1)) returns 2. If tt(index) equals or exceeds the value returned by tt(nWords) an tt(FBB::Exception) is thrown. itb(BIGNUM const &bignum() const) A reference to the tt(BIGNUM) value maintained by the current tt(BigInt) object is returned. itb(char *bigEndian() const) The value represented by the current object is stored in a series of tt(char) typed values in big-endian order. If a value consists of 5 tt(char)s the eight most significant bits will be stored in the tt(char) having index value 0, the eight least significant bits will be stored in the tt(char) having index value 4. When needed simply swap tt(char[i]) with tt(char[j]) (i = 0 .. nBytes/2, j = nBytes-1 .. nBytes/2) to convert to little-endian order. The return value consists of a series of tt(sizeInBytes()) (see below) dynamically allocated tt(char) values. The caller of tt(bigEndian) owns the allocated memory and should eventually delete it again using tt(delete[]). Note that the current object's em(sign) cannot be inferred from the return value. itb(BigInt &clearBit(size_t index)) The current object's bit at index position tt(index) is cleared. itb(BigInt clearBit(size_t index) const) A copy of the current object having its bit at index position tt(index) cleared. itb(long long diophantus(long long *factor1, long long *factor2, long long value1, long long value2)) The integral solution of tt(factor1 * value1 + factor2 * value2 = gcd) is computed. The function returns the greatest common divisor (tt(gcd)) of tt(value1) and tt(value2), and returns their multiplication factors in, respectively, tt(*factor1) and tt(*factor2). The solution is not unique: another solution is obtained by adding tt(k * value2) to tt(factor1) and subtracting tt(k * value1) from tt(factor2). For values exceeding tt(std::numeric_limits::max()) the next member can be used. itb(BigInt diophantus(BigInt *factor1, BigInt *factor2, BigInt const &value1, BigInt const &value2)) The integral solution of tt(factor1 * value1 + factor2 * value2 = gcd) is computed. The function returns the greatest common divisor (tt(gcd)) of tt(value1) and tt(value2), and returns their multiplication factors in, respectively, tt(*factor1) and tt(*factor2). The solution is not unique: another solution is obtained by adding tt(k * value2) to tt(factor1) and subtracting tt(k * value1) from tt(factor2). itb(BigInt &div(BigInt *remainder, BigInt const &rhs)) The current object is divided by tt(rhs). The division's remainder is returned in tt(*remainder). itb(BigInt divc(BigInt *remainder, BigInt const &rhs) const) The quotient of the current object and tt(rhs) is returned. The division's remainder is returned in tt(*remainder). itb(int compare(BigInt const &rsh) const) Using signed values, if the current object is smaller than tt(rhs) -1 is returned; if they are equal 0 is returned; if the current object is larger than tt(ths) 1 is returned (see also tt(uCompare)). itb(BigInt &exp(BigInt const &exponent)) The current object is raised to the power tt(exponent). itb(BigInt expc(BigInt const &exponent) const) The current object raised to the power tt(exponent) is returned. itb(BigInt &expMod(BigInt const &exponent, BigInt const &mod)) The current object is raised to the power tt(exponent) modulo tt(mod). itb(BigInt expModc(BigInt const &exponent, BigInt const &mod) const) The current object raised to the power tt(exponent) modulo tt(mod) is returned. itb(BigInt &gcd(BigInt const &rhs)) The greatest common divisor (gcd) of the current object and tt(rhs) is assigned to the current object. To compute the least common multiple (lcm) the following relationship can be used: verb( lcm(a, b) = a * b / a.gcd(b) ) itb(BigInt gcdc(BigInt const &rhs) const) The greatest common divisor (gcd) of the current object and tt(rhs) is returned. To compute the least common multiple (lcm) the following relationship can be used: verb( lcm(a, b) = a * b / a.gcd(b) ) itb(bool hasBit(size_t index)) tt(True) is returned if the bit at index position tt(index) has been set, tt(false) otherwise. itb(BigInt &inverseMod(BigInt const &mod)) The inverse of the current object modulo tt(mod) is assigned to the current object. This is the value tt(ret) for which the following expression holds true: verb( (*this * ret) % mod = 1 ) itb(BigInt inverseModc(BigInt const &mod) const) This inverse of the current object modulo tt(mod) is returned. itb(bool isNegative() const) Returns tt(true) if the current object contains a negative value. itb(bool isOdd() const) Returns tt(true) if the current object is an odd value. itb(bool isOne() const) Returns tt(true) if the current object equals one (1). itb(BigInt &isqrt()) The current object's integer square root value is assigned to the current object. The integer square root of a value tt(x) is the biggest integral value whose square does not exceed tt(x). E.g., tt(isqrt(17) == 4). An tt(Exception) exception is thrown if the current object's value is smaller than one. itb(BigInt isqrtc() const) The integer square root of the current object is returned. An tt(Exception) exception is thrown if the current object's value is smaller than one. itb(bool isZero() const) Returns tt(true) if the current object equals zero (0). itb(BigInt &lshift()) The current object's bits are shifted one bit to the left. The object's sign remains unaltered. itb(BigInt lshiftc()) The current object's bits shifted one bit to the left are returned. The object's sign will be equal to the current object's sign. itb(BigInt &lshift(size_t nBits)) The current object's bits are shifted tt(nBits) to the left. The object's sign remains unaltered. itb(BigInt lshiftc(size_t nBits) const) The current object's bits shifted tt(nBits) bit to the left are returned. The object's sign will be equal to the current object's sign. itb(BigInt &maskBits(size_t lowerNBits)) The current object's tt(lowerNBits) lower bits are kept, its higher order bits are cleared. The object's sign is not affected. itb(BigInt maskBitsc(size_t lowerNBits) const) A copy of the current object is returned having all but its tt(lowerNBits) lower bits cleared. The sign of the returned object will be equal to the current object's sign. itb(size_t maxWordIndex() const) Returns the maximum tt(Word)-index that can be used with the tt(at) and tt(setWord) members for the current bf(BigInt) value. itb(BigInt &mulMod(BigInt const &rhs, BigInt const &mod)) The current object is multiplied (modulo tt(mod)) by tt(rhs). itb(BigInt mulModc(BigInt const &rhs, BigInt const &mod) const) The current object multiplied (modulo tt(mod)) by tt(rhs) is returned. itb(BigInt &negate()) The current object's value is negated (i.e., the value changes its sign). itb(BigInt negatec() const) The negated value of the current object is returned. itb(BigInt &rshift()) The current object's bits are shifted one bit to the right. The object's sign remains unaltered. itb(BigInt rshiftc()) The current object's bits shifted one bit to the right are returned. The object's sign will be equal to the current object's sign. itb(BigInt &rshift(size_t nBits)) The current object's bits are shifted tt(nBits) to the right. The object's sign remains unaltered. itb(BigInt rshiftc(size_t nBits) const) The current object's bits shifted tt(nBits) bit to the right are returned. The object's sign will be equal to the current object's sign. itb(BigInt &setBit(size_t index)) The bit at index position tt(index) is set. itb(BigInt setBitc(size_t index) const) A copy of the current object is returned having its bit at index position tt(index) set. itb(BigInt &setBit(size_t index, bool value)) The bit at index position tt(index) is set to tt(value). itb(BigInt setBitc(size_t index, bool value) const) A copy of the current object is returned having its bit at index position tt(index) set to tt(value). itb(BigInt &setNegative(bool negative)) The current object's sign will be set to negative if the function's argument is tt(true), it will be set to positive if the function's argument is tt(false). itb(BigInt setNegativec(bool negative) const) A copy of the current object is return having a negative sign if the function's argument is tt(true) and a positive sign if the function's argument is tt(false). itb(void setWord(size_t index, BigInt::Word value)) Assigns tt(value) to the tt(Word) at tt(index). E.g., on a 32 bit architecture, if the bf(BigInt) value equals 2+sups(33), then after tt(setWord(1, 1)) the value has become 2+sups(32). If tt(index) exceeds the value returned by tt(nWords) an tt(FBB::Exception) is thrown. itb(size_t size() const) The number of bytes required to store the current tt(BIGNUM) value is returned. itb(size_t sizeInBits() const) The number of bits required to represent the current tt(BIGNUM) value is returned. itb(size_t sizeInBytes() const) The number of bytes required to store the current tt(BIGNUM) value is returned (returns the same value as the tt(size) memeber does). itb(size_t constexpr sizeOfWord() const) bf(BigInt) values are stored in units of `words', which are unsigned long values. These values may consist of, e.g., 32 or 64 bits. The number of bytes occupied by a `word' is returned: 4 for a 32 bit value, 8 for a 64 bit value, and possibly other values, depending on specific architecture peculiarities. The value returned by this member, therefore, is architecture dependent. itb(BigInt &sqr()) The current object's value is squared. itb(BigInt sqrc() const) The square of the current object is returned. itb(BigInt &sqrMod(BigInt const &mod) const) The current object's value is squared modulo tt(mod). itb(BigInt sqrModc(BigInt const &mod) const) The square (modulo tt(mod)) of the current object is returned. itb(BigInt &subMod(BigInt const &rhs, BigInt const &mod)) tt(Rhs) is subtracted modulo tt(mod) from the current object. itb(BigInt subModc(BigInt const &rhs, BigInt const &mod) const) The difference (modulo tt(mod)) of the current object and tt(rhs) is returned. itb(void swap(BigInt &other)) The current object swaps its value with tt(other). itb(BigInt &tildeBits()) All the bits in the bytes of the current object and the sign of the current object are toggled. So, after verb( Bigint b(5); b.tildeBits(); ) tt(b) contains the value -250. Also see the discussion with tt(operator~()) below. itb(BigInt tildeBitsc() const) A copy of the current object whose bits are toggled is returned. itb(BigInt &tildeInt()) The `tilde' operation is performed on the current object using the standard tt(int) semantics. E.g., ~5 results in -6. Also see the discussion with tt(operator~()) below. itb(BigInt tildeIntc() const) A copy of the current object is returned to which the `tilde' operation has been performed using the standard tt(int) semantics. itb(unsigned long ulong() const) The absolute value stored in the current object is returned as an unsigned long. If it cannot be represented by an unsigned long it returns tt(0xffffffffL). itb(int uCompare(BigInt const &rsh) const) Using absolute values, if the current object is smaller than tt(rhs) -1 is returned; if they are equal 0 is returned; if the current object is larger than tt(ths) 1 is returned (see also tt(uCompare)). ) manpagesection(OVERLOADED OPERATORS) Except for some operators all operators perform their intuitive operations. Where that isn't completely true an explanatory remark is provided. E.g., tt(operator*()) multiplies two tt(BigInt)s, possibly promoting one of the operands; tt(operator*=()) multiplies the lhs by the rhs tt(BigInt), possibly promoting the rhs operand. Here are the available operators: bf(Unary operators:) itemization( itb(bool operator bool() const) Returns tt(true) if the tt(BigInt) value is unequal zero, otherwise tt(false) is returned. itb(BigInt &operator++()) itb(BigInt operator++(int)) itb(BigInt &operator--()) itb(BigInt operator--(int)) itb(BigInt operator-()) itb(int operator[](size_t idx) const) With tt(BigInt) objects it returns the bit-value of the object's tt(idx)th bit as the value 0 or 1. itb(BigInt::Bit operator[](size_t idx)) With non-const tt(BigInt) objects it returns a reference to the bit-value of the object's tt(idx)th bit. When used as em(lvalue) assigning a 0 or non-zero value to the operator's return value will either clear or set the bit. Likewise, the following arithmetic assignment operators may be used: binary or (tt(|=)), binary and (tt(&=)) or binary xor (tt(^=)). When used as em(rvalue) the value of the object's tt(idx)th bit is returned as a tt(bool) value. When inseerted into a tt(std::ostream) the bit's value is displayed as 0 or 1. itb(BigInt operator~()) This operator is em(not) implemented as it cannot be implemented so that it matches the actions of this operator when applied to tt(int) type values. When used on tt(int) values this operator toggles all the tt(int)'s bits. E.g., ~5 represents -6, and ~-6 again equals five. The -6 is the result of the sign bit of tt(int) values. The obvious implementation of tt(BigInt::operator~()) is to toggle all the value's bits and to toggle its sign bit. For 5 this would result in -250: 5, being 101 (binary), fits in one byte, so ~5 becomes 11111010 (binary), which is 250. Its sign must be reversed as well, so it becomes -250. This clearly differs from the value represented by the tt(int) constant ~5: when constructing tt(BigInt(~5)), the value -6 is obtained. It is possible to change the implementation. E.g., after verb( Bigint b(5); b = ~b; ) tt(~b) could be implemented so that it results in the value -6. But this too leads to unexpected results. While tt(5 & ~5 == 0), this would no longer hold true for tt(BigInt) objects: Assuming tt(b) contains 5 then tt(b & ~b) would expand to (binary) tt(101 & (negative)110) which equals (binary) 100. Since either implementation produces unexpected results tt(BigInt::operator~()) was not implemented. Instead two members are offered: tt(tildeBits()), toggling all the bits of all the tt(BigInt) bytes and toggling its sign (so verb( Bigint b(5); b.tildeBits(); ) changes tt(b)'s value into -250), and tt(tildeInt()) changing the object's value into the value that would have been obtained if a tt(BigInt) was a mere tt(int) (so verb( Bigint b(5); b.tildeInt(); ) changes tt(b)'s value into -6). ) bf(Binary operators:) itemization( itb(BigInt operator*(BigInt const &lhs, BigInt const &rhs)) itb(BigInt operator/(BigInt const &lhs, BigInt const &rhs)) This operator returns the quotient of the tt(lhs) object divided by the tt(rhs) object. The remainder is lost (The member tt(div) performs the division and makes the remainder available as well). itb(BigInt operator%(BigInt const &lhs, BigInt const &rhs)) itb(BigInt operator+(BigInt const &lhs, BigInt const &rhs)) itb(BigInt operator-(BigInt const &lhs, BigInt const &rhs)) itb(BigInt operator<<(BigInt const &lhs, size_t nBits)) See also the tt(lshift) members. If tt(lhs) is positive, itb(BigInt operator>>=(BigInt const &lhs, size_t nBits)) See also the tt(rshift) members. itb(BigInt operator&(BigInt const &lhs, BigInt const &rhs)) This operator returns a tt(BigInt) value consisting of the tt(bit_and)-ed bits and sign flags of lhs and rhs operands. Consequently, if one operand is positive, the resulting value will be positive. itb(BigInt operator|(BigInt const &lhs, BigInt const &rhs)) This operator returns a tt(BigInt) value consisting of the tt(bit_or)-ed bits and sign flags of lhs and rhs operands. Consequently, if either operand is negative, the result will be negative. itb(BigInt operator^(BigInt const &lhs, BigInt const &rhs)) This operator returns a tt(BigInt) value consisting of the tt(bit_xor)-ed bits and sign flags of lhs and rhs operands. Consequently, if exactly one operand is negative, the result will be negative. ) bf((Arithmetic) assignment operator(s):) itemization( itb(BigInt &operator=(BigInt const &rhs)) itb(BigInt &operator*=(BigInt const &rhs)) itb(BigInt &operator/=(BigInt const &rhs)) This operator assigns the result of the (integer) division of the current tt(BigInt) object by tt(ths) to the current object. The remainder is lost. The member tt(div) divides and makes the remainder available as well. itb(BigInt &operator%=(BigInt const &rhs)) itb(BigInt &operator+=(BigInt const &rhs)) itb(BigInt &operator-=(BigInt const &rhs)) itb(BigInt &operator<<=(size_t nBits)) See also the tt(lshift) members. itb(BigInt &operator>>=(size_t nBits)) See also the tt(rshift) members. itb(BigInt &operator&=(BigInt const &rhs)) This operator tt(bit_and)s the bits and sign flags of the current object and the rhs operand. itb(BigInt &operator|=(BigInt const &rhs)) This operator tt(bit_or)s the bits and sign flags of the current object and the rhs operand. itb(BigInt &operator^=(BigInt const &rhs)) This operator tt(bit_xor)s the bits and sign flags of the current object and the rhs operand. ) Note that the move operator is not available manpagesection(STATIC MEMBERS) All members returning a tt(BigInt) computed from a set of arguments and not requiring an existing tt(BigInt) object are defined as static members. itemization( itb(BigInt fromText(std::string text, int mode = 0)) This member converts a textual representation of a number to a tt(BigInt) value. Conversion continues until the end of tt(text) or until a character outside of an expected range is encountered. The expected range may be preset by specifying tt(mode) as tt(ios::dec, ios::oct,) or tt(ios::hex) or (the default) the expected range is determined by tt(fromText) itself by inspecting the characters in tt(text). By default if tt(text) contains hexadecimal characters then tt(fromText) assumes that the number is represented as a hexadecimal value (e.g., tt("abc") is converted to the (decimal) value 2748); if tt(text) starts with 0 and contains only characters in the range 0 until (including) 7 then tt(fromText) assumes the number is represented as an octal value (e.g., tt("01234") is converted to the (decimal) value 668). Otherwise a decimal value is assumed. If the text does not represent a valid numerical value (of the given extraction mode) then a tt(FBB::Exception) exception is thrown (tt(fromText: text does not represent a BigInt value)). itb(BigInt rand(size_t size, Msb msb = MSB_IS_ONE, Lsb lsb = ODD)) This member returns a cryptographically strong pseudo-random number of tt(size) bits. The most significant bit(s) can be controlled by tt(msb) (by default bf(MSB_IS_ONE)), the least significant bit can be controlled by tt(lsb) (by default bf(ODD)). Before calling this member the random number generator must have been seeded. From the bf(RAND_add)(3ssl) man-page: OpenSSL makes sure that the PRNG state is unique for each thread. On systems that provide tt(/dev/urandom), the randomness device is used to seed the PRNG transparently. However, on all other systems, the application is responsible for seeding the PRNG by calling bf(RAND_add)(3ssl), bf(RAND_egd)(3ssl), bf(RAND_load_file)(3ssl), or bf(RAND_seed)(3ssl). itb(BigInt randRange(BigInt const &max)) This member returns a cryptographically strong pseudo-random number in the range tt(0 <= number < max). Before calling this member the random number generator must have been seeded (see also bf(rand), described above). itb(BigInt setBigEndian(std::string const &bytes)) The tt(bytes.length()) bytes of tt(bytes) are used to compute a tt(BigInt) object which is returned by this function. The characters in tt(bytes) are interpreted as a series of bytes in big-endian order. See also the member function tt(bigEndian()) above. The returned tt(BigInt) has a positive value. itb(BigInt prime(size_t nBits, BigInt const *mod = 0, BigInt const *rem = 0, PrimeType primeType = ANY)) This member returns a prime number of tt(bBits) bits. If both tt(mod) and tt(rem) are non-zero, the condition prime % mod == rem. (E.g., use tt(prime % mod == 1) in order to suit a given generator). The parameter tt(primeType) can be tt(ANY), tt((prime - 1) / 2) may or may not be a prime. If it is tt(SAFE) then tt((prime - 1) / 2) will be a (so-called em(safe)) prime. itb(BigInt pseudoRand(size_t size, Msb msb = MSB_IS_ONE, Lsb lsb = ODD)) This member returns a potentially predictable pseudo-random number of tt(size) bits. The most significant bit(s) can be controlled by tt(msb) (by default bf(MSB_IS_ONE)), the least significant bit can be controlled by tt(lsb) (by default bf(ODD)). It can be used for non-cryptographic purposes and for certain purposes in cryptographic protocols, but usually not for key generation. itb(BigInt pseudoRandRange(BigInt const &max)) This member returns a potentially predictable pseudo-random number in the range tt(0 <= number < max). ) manpagesection(FREE FUNCTIONS IN THE FBB NAMESPACE) itemization( itb(std::ostream &operator<<(ostream &out, BigInt const &value)) Inserts tt(value) into the provided tt(ostream). If the tt(hex) manipulator has been inserted into the stream before inserting the tt(BigInt) value the value will be displayed as a hexadecimal value (without a leading tt(0x)); if the tt(oct) manipulator has been inserted the value will be represented as an octal value (starting with a 0). The value will be displayed as a decimal value if the tt(dec) manipulator is active. If the tt(BigInt) value is negative its value will be preceded by a minus character. itb(std::istream &operator>>(istream &in, BigInt &value)) Extracts tt(value) from the provided tt(istream). Depending on the currently set extraction mode (tt(dec, oct,) or tt(hex)) the matching set of characters will be extracted from tt(in) and converted to a number which is stored in tt(value). Extraction stops at EOF or at the first character outside of the range of characters matching the extraction mode. if no numerical characters were extracted the stream's tt(failbit) is set. The extracted value may be preceded by a minus character, resulting in an extracted negative value. ) manpagesection(EXAMPLE) verb( #include #include using namespace std; using namespace FBB; int main() { BigInt value(BigInt::prime(100)); BigInt mod(BigInt::rand(50)); BigInt inverse(value.inverseModc(mod)); cout << '(' << value << " * " << inverse << ") % " << mod << " = " << ( value * inverse ) % mod << endl; } ) manpagefiles() em(bobcat/bigint) - defines the class interface manpageseealso() bf(bobcat)(7), bf(diffiehellman)(3bobcat), bf(RAND_add)(3ssl), bf(RAND_egd)(3ssl), bf(RAND_load_file)(3ssl), bf(RAND_seed)(3). manpagebugs() Sep/Oct 2013: due to a change in library handling by the linker (cf. lurl(http://fedoraproject.org/wiki/UnderstandingDSOLinkChange) and lurl(https://wiki.debian.org/ToolChain/DSOLinking)) libraries that are indirectly required are no longer automatically linked to your program. With bf(BigInt) this is tt(libcrypto), which requires programs to link to both tt(bobcat) and tt(crypto). includefile(include/trailer) bobcat-3.19.01/documentation/man/string.yo0000644000175000017500000002416312222576536017426 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::String)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Operations on std::string objects) manpagename(FBB::String)(Several operations on bf(std::string) objects) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() This class offers facilities for often used transformations on tt(std::string) objects, but which are not supported by the tt(std::string) class itself. All members of bf(FBB::String) are static. manpagesection(NAMESPACE) bf(FBB)nl() All members, operators and manipulators, mentioned in this man-page, are defined in the namespace bf(FBB). manpagesection(INHERITS FROM) -- manpagesection(ENUMERATION) itemization( itb(Type) This enumeration indicates the nature of the contents of an element in the array returned by the overloaded tt(split) members (see below). bf(DQUOTE), a subset of the characters in the matching tt(string) element was delimited by double quotes in the in the string that was parsed by the tt(split) members. bf(DQUOTE_UNTERMINATED), the contents of the string that was parsed by the tt(split) members started at some point with a double quote, but the matching ending double quote was lacking. bf(ESCAPED_END), the contents of the string that was parsed by the tt(split) members ended in a mere backslash. bf(NORMAL), a normal string; bf(SEPARATOR), a separator; bf(SQUOTE), a subset of the characters in the matching tt(string) element was delimited by quotes in the in the string that was parsed by the tt(split) members. bf(SQUOTE_UNTERMINATED), the contents of the string that was parsed by the tt(split) members started at some point with a quote, but the matching ending quote was lacking. ) manpagesection(TYPEDEF) The bf(typedef SplitPair) represents bf(std::pair) and is used in the second variant of the bf(split) member (see below). manpagesection(HISTORY) Initially this class was derived from bf(std::string). Deriving from tt(std::string), however, is considerd bad design as tt(std::string) was not designed as a base-class. bf(FBB::String) offers a series of em(static) member functions providing the facilities originally implemented as non-static members. manpagesection(STATIC MEMBER FUNCTIONS) itemization( itb(char const **argv(std::vector const &words)) Returns a pointer to an allocated series of pointers to the bf(C) strings stored in the vector tt(words). The caller is responsible for returning the array of pointers to the common pool, but should em(not) delete the bf(C)-strings to which the pointers point. The last element of the returned array is guaranteed to be a 0-pointer. itb(int casecmp(std::string const &lhs, std::string const &rhs)) Performs a case-insensitive comparison between the two tt(std::string) objects. A negative value is returned if tt(lhs) should be ordered before tt(rhs); 0 is returned if the two strings have identical contents; a positive value is returned if the tt(lhs) object should be ordered beyond tt(rhs). itb(std::string escape(std::string const &str, char const *series = "'\"\\")) Returns a copy of the tt(str) object in which all characters in tt(series) are prefixed by a backslash character. itb(std::string lc(std::string const &str) const) Returns a copy of the tt(str) object in which all letters were transformed to lower case letters. itb(std::string trim(std::string const &str)) Returns a copy of the tt(str) object from which the leading and trailing blanks have been removed. itb(std::vector split(Type *type, std::string const &str, char const *separators = " \t", bool addEmpty = false)) Returns a vector containing the elements in tt(str) which are separated from each other by at least one of the characters found in tt(*separators). The member's first parameter points to a tt(Type) variable, which will show tt(DQUOTE_UNTERMINATED, SQUOTE_UNTERMINATED,) or tt(ESCAPED_END) in cases where the contents of tt(str) are ill-formed, or tt(NORMAL) if tt(str)'s contents shows not syntactic errors (i.e., ill-formed strings or escape-sequences). If the corresponding argument equals 0 then no tt(Type) indication is provided. If the parameter tt(addEmpty) is set to tt(true), then individual separators encountered in tt(str) are stored as empty strings in tt(words) (e.g., if two elements are separated by three blank spaces, then the returned vector contains three empty strings between the two elements). If an element in tt(str) contains a double quote (tt(")), then all characters from the initial double quote through the matching double quote character are processed as follows: the surrounding double quotes are removed, and the remaining characters are em(unescaped) using the tt(String::unescape) member. The resulting unescaped string is added to the element currently under construction. E.g., if tt(str) contains verb( string="\"hello world\"" ) then the element becomes verb( string="hello world" ) If an element in tt(str) contains a single quote (tt(')), then all characters between the initial quote and the matching quote character are literally appended to the element currently under construction. E.g., if tt(str) contains verb( string='"hello\ world"' ) then the element becomes verb( string="hello\ world" ) Backslash characters encountered in tt(str) outside of single or double quoted strings are unescaped (using tt(String::unescape)) and the resulting character is appended to the element currently under construction. E.g., if tt(str) contains verb( string=\"hello\ world\" ) then the element becomes verb( string="hello world" ) itb(std::vector split(std::string const &str, char const *separators = " \t", bool addEmpty = false)) Same functionality as the previous tt(split) member, but the tt(words) vector is filled with pairs, of which the first elements represent the recognized strings, and the second elements are values of the tt(String::Type) enumeration. If bf(addEmpty) is requested, then the bf(string) elements contain the actual contents of the separator, while the bf(Type) elements are set to bf(SEPARATOR). If the returned vector is not empty then the tt(second) member of the last element may be tt(DQUOTE_UNTERMINATED, SQUOTE_UNTERMINATED,) or tt(ESCAPED_END) in cases where the contents of tt(str) are ill-formed. itb(size_t split(std::vector *words, std::string const &str, char const *separators = " \t", bool addEmpty = false)) Fills tt(words) with all elements of the tt(str) object, separated by any of the characters in tt(separators). If the parameter tt(addEmpty) is set to tt(true), the individual separators are stored as empty strings in tt(words). If a word starts with tt(") or tt(') all characters until a matching terminating tt(") or tt(') at the end of a word are considered as one word. The surrounding quotes are not stored. The function returns the number of elements in the vector pointed to by tt(words). This vector is initially cleared. itb(size_t split(std::vector *words, std::string const &str, char const *separators = " \t", bool addEmpty = false)) Same functionality as the former member, but the tt(words) vector is filled with pairs, of which the first elements are the recognized strings, and the second elements values of the tt(String::Type) enumeration. If bf(addEmpty) is requested, then the bf(string) elements contain the actual contents of the separator, while the bf(Type) elements are set to bf(SEPARATOR). itb(std::string unescape(std::string const &str)) Returns a copy of the tt(str) object in which the escaped (i.e., prefixed by a backslash) characters have been interpreted. All standard escape characters (tt(\a), tt(\b), tt(\f), tt(\n), tt(\r), tt(\t), tt(\v)) are recognized. If an escape character is followed by tt(x) the next two characters are interpreted as a hexadecimal number. If an escape character is followed by an octal digit, then the next three characters following the backslash are interpreted as an octal number. In all other cases, the backslash is removed and the character following the backslash is kept. itb(std::string uc(std::string const &str)) Returns a copy of the tt(str) object in which all letters were capitalized. ) manpagesection(EXAMPLE) verb( #include #include #include using namespace std; using namespace FBB; char const *type[] = { "DQUOTE_UNTERMINATED", "SQUOTE_UNTERMINATED", "ESCAPED_END", "SEPARATOR", "NORMAL", "DQUOTE", "SQUOTE", }; int main(int argc, char **argv) { cout << "Program's name in uppercase: " << String::uc(argv[0]) << endl; if (argc == 1) cout << "Provide any argument to suppress SEPARATOR fields\n"; while (true) { cout << "Enter a line, or empty line to stop:" << endl; String line; if (!getline(cin, line) || !line.length()) break; vector splitpair; cout << "Split into " << line.split(&splitpair, " \t", argc == 1) << " fields\n"; for ( vector::iterator it = splitpair.begin(); it != splitpair.end(); ++it ) cout << (it - splitpair.begin() + 1) << ": " << type[it->second] << ": `" << it->first << "', unescaped: `" << String(it->first).unescape() << "'" << endl; } return 0; } ) manpagefiles() em(bobcat/string) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/readlinestream.yo0000644000175000017500000002664412222576536021125 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::ReadLineStream)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz) (Editing input lines) manpagename(FBB::ReadLineStream) (std::istream offering line-editing and history) manpagesynopsis() bf(#include )nl() Linking option: -lreadline -lbobcat manpagedescription() A bf(FBB::ReadLineStream) object is a tt(std::istream) objects, allowing line-editing and history manipulation. The bf(ReadLineStream) class uses Gnu's readline library to allow editing of input lines. The tt(ReadLineStream) object can be used to construct a tt(std::istream) allowing in-line editing of lines read from the terminal. All lines may be preceded by a configurable prompt. Since Gnu's readline library operates on global data there can only be one bf(ReadLineStream) (and underlying bf(ReadLineBuf)) object. bf(ReadLineStream) is a singleton class: in any program there can only be one bf(ReadLineStream) object. bf(ReadLineStream) offers editing capabilities while the user is entering lines. Like Gnu's bf(readline)(3) function, the line editing commands are by default similar to those of bf(emacs)(1), but can easily be reconfigured, e.g. to offer bf(vi)(1)-like characteristics. History manipulation is provided as an option. The collected history may be accessed for reading using an bf(FBB::ReadLineHistory) object. Specific information about the facilities offered by the Gnu software used by bf(ReadLineStream) is provided in the GNU Readline Library documentation (tt(http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html)). Gnu's tt(readline) function reads its information from the standard input file. Programs using tt(ReadLineStream) should normally not extract information from tt(std::cin). However, as the standard input file has a file descriptor (0), redirection should be possible (e.g., using tt(FBB::Redirector)). When the command line is kept, history expansion is offered as an option. History expansion introduces words from the history list into the input stream, making it easy to repeat commands, to insert elements of a previous input line into the current input line, or to fix errors in previous command lines. History expansion is usually performed immediately after a complete line is read. The line selected from the history is called the tt(event), and the portions of that line that are processed are called tt(words). Various modifiers are available to manipulate selected words. This is comparable to the way a program like bf(bash)(1) breaks up its input line into `words'. History expansion is introduced by the use of the history expansion character, by default equal to the tt(!)-character. Only backslash (tt(\)) and single quotes can change the history expansion character into a normal character. The remainder of this section is copied almost verbatim from the bf(history)(3) man-page. The reader is referred to that man-page or to the Gnu History Library documentation for further details. The following bf(event designators) are supported: itemization( itt(!): starts a history substitution, except when followed by a blank, newline, tt(=) or tt(CHAR(40)). itt(!n): refers to command line n. itt(!-n): refers to the current command line minus n. itt(!!) refers to the previous command. This is a synonym for `!-1'. itt(!string) refers to the most recent command starting with string. itt(!?string[?]) refers to the most recent command containing string. The trailing tt(?) may be omitted if string is followed immediately by a newline. itt(^string1^string2^) (quick substitution) repeats the last command, replacing tt(string1) with tt(string2). Equivalent to tt(!!:s/string1/string2/). itt(!#) the entire command line typed so far. ) bf(Word Designators) Word designators are used to select desired words from the event. A tt(:) separates the event specification from the word designator. It may be omitted if the word designator begins with a tt(^, $, *, -), or tt(%). Words are numbered from the beginning of the line, with the first word being denoted by 0 (zero). Words are inserted into the current line separated by single spaces. itemization( itt(0) (zero) The zeroth word. For the shell, this is the command word. itt(n) The nth word. itt(^) The first argument. That is, word 1. itt($) The last argument. itt(%) The word matched by the most recent tt(?string?) search. itt(x-y) A range of words; `-y' abbreviates `0-y'. itt(*) All of the words but the zeroth. This is a synonym for tt(1-$). It is not an error to use * if there is just one word in the event; the empty string is returned in that case. itt(x*) Abbreviates tt(x-$). itt(x-) Abbreviates tt(x-$) like tt(x*), but omits the last word. ) If a word designator is supplied without an event specification, the previous command is used as the event. bf(Modifiers) After the optional word designator, there may appear a sequence of one or more of the following modifiers, each preceded by a tt(:). itemization( itt(h) removes a trailing file name component, leaving only the head. itt(t) removes all leading file name components, leaving the tail. itt(r) removes a trailing suffix of the form tt(.xxx), leaving the basename. itt(e) removes all but the trailing suffix. itt(p) prints the new command but does not execute it. itt(q) quotes the substituted words, escaping further substitutions. itt(x) quotes the substituted words as with q, but break into words at blanks and newlines. itt(s/old/new/) substitutes new for the first occurrence of old in the event line. Any delimiter can be used in place of tt(/). The final delimiter is optional if it is the last character of the event line. The delimiter may be quoted in old and new with a single backslash. If tt(&) appears in new, it is replaced by old. A single backslash will quote the tt(&). If tt(old) is null, it is set to the last old substituted, or, if no previous history substitutions took place, the last string in a tt(!?string[?]) search. itt(&) repeats the previous substitution. itt(g) Causes changes to be applied over the entire event line. This is used in conjunction with tt:s) (e.g., tt(:gs/old/new/)) or tt(:&). If used with tt(:s), any delimiter can be used in place of tt(/), and the final delimiter is optional if it is the last character of the event line. An a may be used as a synonym for tt(g). itt(G) Apply the following tt(s) modifier once to each word in the event line. ) includefile(include/namespace) manpagesection(INHERITS FROM) tt(FBB::ReadLineBuf) (privately), tt(std::istream) (publicly) manpagesection(ENUMERATIONS) The tt(enum Type) defines the following value: itemization( itt(DONT_EXPAND_HISTORY): history expansion is not requested; itt(EXPAND_HISTORY): history expansion is requested. ) The tt(enum Expansion) provides meaningful return values for the history expansion process. Its values are: itemization( itt(DONT_EXEC): history expansion succeeded, but the expanded line should not be executed. E.g., after entering the line verb( ls * ) the line verb( !!:p ) should cause the using program to em(display), rather than exectute tt(ls *). Note that interpretation of this expansion return value is not the task of the bf(ReadLineBuf) object, but of the program using the bf(ReadLineBuf) object. itt(ERROR): the history expansion failed. See also the member tt(expansionError) below; itt(EXPANDED): the history expansion succeeded; itt(NO_EXPANSION): no history expansion took place. ) manpagesection(CONSTRUCTORS) Preamble: since there can only be one bf(ReadLineBuf) object, any attempt to define a second bf(ReadLineStream) object will fail as there can only be a single bf(ReadLineBuf) object in any program. An attempt to define a second bf(ReadLineBuf) object results in a tt(logic_error) exception being thrown. itemization( itb(ReadLineStream(std::string const &prompt = "", Type type = NO_EXPANSION)) This constructor initializes the tt(ReadLineStream) object with an initial prompt, using a history of at most tt(std::numeric_limits::max()) lines, by default not using history expansion. itb(ReadLineStream(std::string const &prompt, size_t historySize, Type type = NO_EXPANSION)) This constructor initializes the tt(ReadLineStream) with an initial prompt, an initial history of a predefined maximum size, by default not using history expansion. Specifying a history size 0 results in no history being kept, any value equal to or exceeding the predefined constant tt(std::numeric_limits::max()) results in a history of at most tt(std::numeric_limits::max()) lines. If no history is requested but tt(type) is specified as tt(EXPAND_HISTORY) a tt(logic_error) exception is thrown. ) The standard copy constructor is not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::ReadLineStream) inherits from this class. itemization( itb(ReadLineStream::Expansion expansion() const) The status of the history expansion after retrieving a line from the terminal is returned. Its value is determined after each line retrieved from the terminal. If no history expansion is requested it returns tt(Expansion::ERROR). itb(std::string const &expansionError() const) A short textual description of the nature of the error when tt(expansion) returns tt(Expansion::ERROR) is returned. If no history expansion is requested an empty string is returned. itb(bool setExpansion(Type type)) History expansion can be activated or stopped using this member. When history expansion is requested but the bf(ReadLineStream) object maintains no history the function returns tt(false). Otherwise it returns tt(true). itb(void setPrompt(std::string const &prompt = "")) The prompt that is displayed in front of the next line read from the terminal can be modified by this member. When called without arguments no prompt will be displayed. tt(setPrompt) can be called while input lines are being received. The new prompt will be active after the current line has been read from the terminal. itb(bool useTimestamps(std::string (*timestamp)() = 0)) When initialized with the address of a function returning a tt(std::string) the entered commands will be given a timestamp equal to the text returned by the function pointed to by tt(timestamp). The timestamps can be retrieved using the bf(ReadLineHistory)(3) object. By default or after passing an explicit 0-pointer to tt(useTimestamps) no timestamps are stored. The value tt(false) is returned when no history is kept, otherwise tt(true) is returned. ) manpagesection(EXAMPLE) verbinclude(../../readlinestream/driver/driver.cc) manpagefiles() em(bobcat/readlinebuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(readline)(3), bf(readlinebuf)(3), bf(readlinehistory)(3) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/inetaddress.yo0000644000175000017500000001134712222576536020425 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::InetAddress)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Network Byte Order) manpagename(FBB::InetAddress) (Converting between host byte order and network byte order) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() Computers differ their word-byte order, called `endianness'. A little-endian computer has its least significant byte at the byte having the lower address of a two-byte value, whereas a big-endian computer has its least significant byte at at the byte having the higher address of a two-byte value. In order to allow these computers to communicate over over Internet, em(host byte order) was designed. Objects of the class bf(FBB::InetAddress) may be used to convert between network byte order and host byte order (and vice versa). The class only has a few public members. Most members are protected, and bf(FBB::InetAddress) is therefore primarily used as a base class from which other classes are derived. In practice there will be little need to construct objects of the class bf(FBB::InetAddress), which is primarily a support class for the bf(FBB) socket-classes. Internally, all data are stored in network byte order. As the class' constructors depend on the proper functioning of members of the bf(FBB:GetHostent) class, the class' objects can only be constructed when the host whose name or address is searched can be resolved by a name resolution process, e.g., bf(bind)(1). Objects of the class bf(FBB::InetAddress) store address information about a host in a bf(struct sockaddr_in) data member. A bf(struct sockaddr_in) is the data type used to represent socket addresses in the Internet namespace. It has the following members: itemization( itb(sa_family_t sin_family) This identifies the address family or format of the socket address. It holds the value bf(AF_INET). itb(struct in_addr sin_addr) This is the Internet address of the host machine stored as a binary value. itb(size_t short int sin_port) This field holds the port number. ) includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(PROTECTED CONSTRUCTORS) itemization( itb(InetAddress(std::string const &host, uint16_t port)) This constructor expects a host name or dotted decimal address and and an (size_t) port number, and determines the host's address information. An bf(FBB::Exception) exception is thrown if the address could not be determined. itb(InetAddress(uint16_t port)) This constructor constructs the `generic' address information that is used when constructing, e.g. server sockets. itb(InetAddress(sockaddr_in const &address)) This constructor constructs an bf(FBB::InetAddress) object from an initialized bf(sockaddr_in) object. It is primarily used to promote a bf(sockaddr_in) to an bf(FBB::InetAddresss). ) The (public) copy constructor is available. manpagesection(MEMBER FUNCTIONS) itemization( itb(uint16_t port() const) Accessor returning the object's port value. itb(std::string dottedDecimalAddress() const) Accessor returning the object's Internet address as a dotted decimal string. If the address could not be determined, an bf(FBB::Exception) object is thrown. itb(size_t size() const) Accessor returning the size of the object's bf(sockaddr_in) (address) information. itb(sockaddr const *sockaddrPtr() const) Accessor returning the pointer to the object's bf(sockaddr) data member. itb(sockaddr_in const *sockaddr_inPtr() const) Accessor returning the pointer to the object's bf(sockaddr_in) data member. ) manpagesection(PROTECTED MEMBER FUNCTIONS) itemization( itb(sockaddr *sockaddrPtr()) This member returns the object's address information as a pointer to a modifiable bf(struct sockaddr). This allows (contrary to the public member having the same name) derived objects to manipulate the object's address information directly. itb(sockaddr_in *sockaddr_inPtr()) This member returns the object's address information as a pointer to a modifiable bf(struct sockaddr_in). This allows (contrary to the public member having the same name) derived objects to manipulate the object's address information directly. ) manpagesection(EXAMPLE) verbinclude(../../inetaddress/driver/driver.cc) manpagefiles() em(bobcat/inetaddress) - defines the class interface manpageseealso() bf(bind)(1), bf(bobcat)(7), bf(gethostent)(3bobcat), bf(socketbase)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/cgi.yo0000644000175000017500000003506012222576536016660 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::CGI)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (CGI interface) manpagename(FBB::CGI)(handles GET and POST submitted form data) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() The class tt(CGI) offers an interface to data submitted by web-forms. The data is sent to a script handling the data using a tt(
) stanza. Very often this is indeed a script, like a Perl script, but there is no need to use a scripting language. The class tt(CGI) allows bf(C++) programmers to process the form by an executable usually resulting in faster processing and in construction time benefits from the type safety offered by bf(C++). The class tt(CGI) automatically handles data submitted using the tt(GET) method as well as data submitted using the tt(POST) method. By default the class's constructor writes the customary tt(Content-type) header lines to the standard output stream. Additional (html) output of a reply page must be provided by other code. Therefore, a program processing an uploaded form will have an organization comparable to the following basic setup: verb( // assume includes and namespace std/FBB were defined int main() { CGI cgi; cout << "\n"; if (parametersOK(cgi)) { process(cgi); generateReplyPage(); } else generateErrorPage(); cout << "\n; } ) When errors in the received form-data are detected an error message is written to the standard output stream and an tt(FBB::Exception) exception is thrown. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(TYPEDEF) itemization( itb(CGI::MapStringVector) A shorthand for tt(std::unordered_map >), which is the data type in which form-variables are stored. ) manpagesection(ENUMERATIONS) The tt(CGI::Method) enumeration specifies values indicating the way the form's data were submitted: itemization( itb(CGI::UNDETERMINED) Used internally indicating that the form's method was neither tt(GET) nor tt(POST). itb(CGI::GET) Indicates that the tt(GET) method was used when submitting the form's data; itb(CGI::POST) Indicates that the tt(POST) method was used when submitting the form's data. ) The tt(CGI::Create) enumeration is used to request or suppress creation of the directory to contain any file uploaded by a form: itemization( itb(CGI::DONT_CREATE_PATH) When uploading files, the destination directory must exist; itb(CGI::CREATE_PATH) When uploading files, the destination directory will be created. ) manpagesection(CONSTRUCTORS) itemization( itb(CGI(bool defaultEscape = true, char const *header = "Content-type: text/html", std::ostream &out = std::cout)) The default constructor writes the standard content type header to the standard output stream and will use tt(std::cout) for output. Specifying tt(0) as header suppresses outputting the tt(Content-type) line. Otherwise the content type line is also followed by two tt(\r\n) character combinations. By default all characters in retrieved form-variables are escaped. The overloaded insertion operators (see below) can be used to modify the default set of characters to escape. The backslash is used as the escape character. The escape-prefix is not used if the tt(defaultEscape) value is specified as tt(false) and if no insertions into the bf(CGI) object were performed. ) The copy and move constructors are available. manpagesection(OERLOADED OPERATORS) bf(Note:) the following three insertion operators, defining sets of characters that should be escaped, can only be used before calling any of the tt(param, begin) or tt(end) members. As soon as one of these latter three members has been called the set of characters to be escaped is fixed and attempts to modify that set is silently ignored. itemization( itb(char const *operator[](std::string const &key) const) The index operator returns the value of the environment variable specified as the index. 0 is returned if the variable specified at tt(key) is not defined. itb(CGI &operator<<(std::string const &accept)) This member's actions are suppressed once tt(param, begin) or tt(end) (see below) has been called. The insertion operator can be used to fine-tune the set of characters that are escaped in strings returned by tt(param) (see below). Depending on the value of the constructor's tt(defaultEscape) parameter characters inserted into the tt(CGI) object will or will not be escaped by a backslash. If the constructor's tt(defaultEscape) parameter was specified as tt(true) then the insertion operator can be used to define a set of characters that are em(not) escaped. If tt(defaultEscape) was specified as tt(false) then the insertion operator will define a set of characters that em(will) be escaped. The backlash itself is always escaped and a request to use it unescaped is silently ignored. The tt(accept) string can be specified as a regular expression character set, without the usual surrounding square brackets. E.g., an insertion like tt(cgi << "-a-z0-9") defines the set consisting of the dash, the lower case letters and the digits. Individual characters, character ranges (using the dash to specify a range) and all standard character classes (tt([:alnum:], [:alpha:], [:cntrl:], [:digit:], [:graph:], [:lower:], [:print:], [:punct:], [:space:], [:upper:]), and tt([:xdigit:])) can be used to specify a set of characters. In addition to these standard character classes the class tt([:cgi:]) can be used to define the set consisting of the characters tt(" ' ` ;) and tt(\). Note that standard and tt([:cgi:]) character classes em(do) require square brackets. When a series of insertions are performed then the union of the sets defined by these insertions are used. bf(Note): using unescaped single quotes, the double quotes, backtick characters and semicolons in CGI-programs might be risky and is not advised. itb(CGI &operator<<(int c)) This member's actions are suppressed once tt(param, begin) or tt(end) (see below) has been called. This insertion operator is used to change the default escape handling of a single character tt(c). The tt(int) parameter is cast internally to a tt(char). itb(CGI &operator<<(std::pair range)) This member's actions are suppressed once tt(param, begin) or tt(end) (see below) has been called. This insertion operator can be used to change the default escape handling of a range of characters. The pair's second character must be equal to or exceed the position of the pair's first character in the ASCII collating sequence or the member will have no effect. itb(std::ostream &std::operator<<(std::ostream &out, CGI const &cgi)) tt(CGI) objects can be inserted into tt(ostreams) to display the characters that will appear escaped in strings returned by the tt(param()) member function. Each character for which tt(isprint()) returns tt(true) will be displayed as character, surrounded by single quotes. For all other characters their ASCII values are displayed. Each character is displayed on a line by itself. ) The copy and move assignment operators are available. manpagesection(MEMBER FUNCTIONS) itemization( itb(CGI::MapStringVector::const_iterator begin()) Returns the begin iterator of the form's parameter map. Iterator values unequal to tt(end) (see below) point to a pair of values, the first of which is the name of a field defined by the form, the second is a vector of strings containing the field's value(s). See also the description of the tt(param) member below. itb(CGI::MapStringVector::const_iterator end()) Returns the end iterator of the form's parameter map. itb(unsigned long long maxUploadSize() const) Returns the current maximum file upload size in bytes. itb(CGI::Method method() const) Returns the method that was used when the form was submitted (either tt(CGI::GET) or tt(CGI::POST)). itb(std::vector const ¶m(std::string const &variable)) Returns the value of the form-variable specified by the function's argument. An empty vector is returned if the variable was not provided by the form's data. If the same variable was specified multiple times or if its value extends over multiple lines (only with tt(multipart/form-data)) then the vector contains multiple strings. With tt(GET) and tt(POST) methods not using tt(multipart/form-data) input fields extending over multiple lines are stored in one string, using tt(\r\n) combinations between those lines. When files are uploaded the vectors contain sets of four strings. The first string provides the path nme of the uploaded file; the second string provides the file name specified in the form itself (so it is the name of the file at the remote location); the third string shows the content type specified by the remote browser (e.g., tt(application/octet-stream)), the fourth string contains tt(OK) if the file was successfully uploaded and tt(truncated) if the file was truncated. Existing files will not be overwritten. When uploading a file a usable filename must be found within 100 trials. itb(std::string param1(std::string const &variable) const) Returns the first element of the tt(vector) returned by the tt(param) member or an empty string if tt(variable) was not defined by the received form. itb(std::string const &query() const) Returns the query-string submitted with tt(CGI::GET) or tt(CGI::POST) forms (if the tt(POST)ed form specified tt(ENCTYPE="multipart/form-data") the query string is empty). itb(report+CHAR(40)CHAR(41)) The tt(report) member silently returns if no errors were encountered while processing form-data. Otherwise, the tt(html) file generated by the tt(CGI) program displays a line starting with tt(FBB::CGI), followed by the status report. The following status report messages are presently defined: tt(Content-Disposition not recognized in:), which is followed by the line where the tt(Content-Disposition) was expected. This may occur when processing tt(multipart/form) data. tt(Invalid multipart/form-data). This message can be generated when readling lines while processing tt(multipart/form) data. tt(GET/POST REQUEST_METHOD not found). This message is shown if the program couldn't find the form's tt(REQUEST_METHOD) type (i.e., tt(GET) or tt(POST)). tt(Invalid CONTENT_LENGHT in POSTed form). This message is shown if the content-length header has an incorrect value. tt(Content-Type not found for file-field), followed by the file's field name. This message is shown if no tt(Content-Type) specification was found in an uploaded form. tt(Can't open a file to write an uploaded file). This message indicates that the CGI program was unable to open a file to write an uploaded file to. This can be caused by an overfull disk or partition or by incorrect write-permissions. tt(multipart/form-data: no end-boundary found). This message is shown if the end-boundary was missing in a tt(multipart/form-data) form. itb(void setFileDestination(std::string const &path, std::string const &prefix = "", Create create = CREATE_PATH)) This member is used to specify the path and prefix of uploaded files. Uploaded files will be stored at tt(path/prefixNr) where tt(Nr) is an internally used number starting at one. When tt(CREATE_PATH) is specified tt(path) must be available or the bf(CGI) object must be able to create the path. If tt(DONT_CREATE_PATH) is specified the specified path must be available. If not, an tt(FBB::Exception) exception will be thrown. itb(void setMaxUploadSize(size_t maxSize, int unit = 'M')) This member can be used to change the maximum size of uploaded files. Its default value is 100Mb. The tt(unit) can be one of tt(b) (bytes, the default), tt(K) (Kbytes), tt(M) (Mbytes) or tt(G) (Gbytes). Unit-specifiers are interpreted case insensitively. File uploads will continue until the maximum upload size is exceeded, followed by discarding any remainder. ) The first time one of the tt(param(), begin()) or tt(end()) members is called these members may detect errors in the the received form data. If so, an error message is written to the standard output stream and an tt(FBB::Exception) exception will be thrown. manpagesection(STATIC MEMBERS) itemization( itb(std::string dos2unix(std::string const &text)) This member converts all tt(\r\n) character combinations in tt(text) into plain tt(\n) characters, returning the converted text. itb(std::string unPercent(std::string const &text)) This member converts all tt(%xx) encoded characters into their corresponding ASCII values. Also, tt(+) characters are converted to single blank spaces. The converted string is returned. ) manpagesection(EXAMPLE) verbinclude(../../cgi/driver/driver.cc) To test the program's tt(get) form processing, call it as tt(driver get '[:cgi:]'), with the file tt(get) containing: verbinclude(../../cgi/driver/get) To test the program's tt(post) form processing, call it as tt(driver post1 '[:cgi:]'), using tt(post1) and tt(post1.cin) found in Bobcat's source archive under tt(../cgi/driver). manpagefiles() em(bobcat/cgi) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/repeat.yo0000644000175000017500000000521712222576536017377 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::repeat)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (repeated function calls) manpagename(FBB::repeat)(call a (member) function a fixed number of times) manpagesynopsis() bf(#include )nl() manpagedescription() The bf(FBB::repeat) function template allows a function or member function to be called a certain number of times. The functions or member functions may define arguments. Arguments to these functions are specified when tt(repeat) is called, and are perfectly forwarded by the tt(repeat) function template to the (member) function called by tt(repeat). The first argument of the tt(repeat) function template defines the number of times the (member) function must be called. The tt(FBB::repeat) function template are defined tt(inline), allowing the compiler to `optimize away' the tt(repeat) function call itself. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(REPEAT FUNCTION TEMPLATE) The tt(repeat) function template is declared as: verb( template void repeat(Counter counter, First &&first, Params &&...params); ) In this declaration, itemization( it() bf(Counter) represents the counter's type. Usually an tt(int) or tt(size_t). When calling tt(repeat) tt(counter) must be initialized to the number of times tt(repeat) must call the (member) function (see below); it() bf(First) represents the prototype of a function or the name of a class. name of a class. Likewise, tt(first) either is the address (name) of the function to be called or the name of an object of class type tt(First). In the latter case the object may or may not be a tt(const) object. it() bf(...Params) represents the set of parameter types of arguments which must be perfectly forwarded to the called function. If tt(first) represents a class type object, the first argument em(must) be the address of a member function of the class tt(First). ) manpagesection(EXAMPLES) verbinclude(../../repeat/driver/driver.cc) manpagefiles() em(bobcat/repeat) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() Be careful when using overloaded functions, as the template argument resolution mechanism may be unable to determine which function to call. If overloaded functions must be used, a tt(static_cast) is likely required to disambiguate your intentions. includefile(include/trailer) bobcat-3.19.01/documentation/man/hostent.yo0000644000175000017500000001102312222576536017573 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Hostent)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (struct hostent wrapper) manpagename(FBB::Hostent)(Wrapper around a bf(struct hostent)) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(@CLASS) objects are wrappers around bf(hostent) structs which may be used by other objects. A bf(struct hostent) is defined as follows: verb( struct hostent { char *h_name; // official name of host char **h_aliases; // alias list int h_addrtype; // host address type (always AF_INET) int h_length; // length of address char **h_addr_list; // list of addresses } ) The tt(address) fields are binary values of the addresses, each address requiring tt(h_length) bytes, the last address being equal to 0. The bf(@CLASS) objects offer a bf(C++)-like interface to this struct. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) itemization( itb(Hostent(hostent const *hostentPtr)) This constructor initializes an bf(@CLASS) object from an existing bf(hostent) struct. Functions like bf(gethostbyname)(3) and bf(gethostbyaddress)(3) return pointers to bf(hostent) structs. ) The default, copy and move constructors are available. manpagesection(MEMBER FUNCTIONS) itemization( itb(size_t addressLength() const) This member returns the length of the binary addresses in bytes. itb(size_t addressType() const) This member returns the type of the address. Currently this is always bf(AF_INET). itb(char const *alias(size_t index) const) This member returns alias `tt(index)' of the host. The first alias has tt(index 0). If alias `tt(index)' does not exist, 0 is returned. itb(char const * const *beginAlias() const) This member returns an iterator to the first alias. The hostname itself is not included in the list of aliases. itb(char const *binaryAddress(size_t index) const) This member returns the binary address `tt(index)' of the host. The first address has tt(index 0). If address `tt(index)' does not exist, 0 is returned. The pointer to the binary address points to a series of bf(addressLength()) bytes. Note that the returned address is in em(network byte order). It can be converted to host byte order by the functions described in bf(byteorder)(3). itb(std::string dottedDecimalAddress(size_t index) const) This member returns address `tt(index)' as a dotted decimal address in a string. The first address has tt(index 0). If address `tt(index)' does not exist, an empty string is returned. itb(char const * const *endAlias() const) This member returns an iterator pointing beyond the last alias. itb(char const *hostname() const) This member returns the standard (first) name of the host. itb(size_t nAddresses() const) This member returns the number of addresses that are available. When requesting a particular address, the requested index should be less than the value returned by this member. itb(size_t nAliases() const) This member returns the number of aliases that are available. When requesting a particular alias, the requested index should be less than the value returned by this member. itb(void swap(Hostent &other)) The current tt(Hostent) object's contents are swapped with the other object's contents. ) The overloaded assignment operator and the move-aware overloaded assignment operators are available. manpagesection(EXAMPLE) verb( #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { Hostent he(gethostbyname("localhost")); cout << "The local hostname = " << he.hostname() << endl; cout << "All aliases: " << endl; copy(he.beginAlias(), he.endAlias(), ostream_iterator(cout, "\n")); cout << "Addresses:\n"; for (size_t idx = 0; idx < he.nAddresses(); idx++) cout << he.dottedDecimalAddress(idx) << endl; return 0; } ) manpagefiles() em(bobcat/hostent) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/signal.yo0000644000175000017500000001305212257522663017370 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Signal)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (signal handler) manpagename(FBB::Signal)(Signal Handler) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() Signals have the well known drawback that signals arrive free of context. E.g., assume a program runs a flow control loop like this: verb( void Class::run() { while (d_continue) handleTasks(); cleanup(); } ) then if the program needs to recognize a termination signal then the typical signal handler looks like this: verb( void signalHandler(int signal) { // perform required actions } ) Since the tt(signalHandler) is called asynchronically, there is no context available, and the usual way of communicating between objects and signal handlers is via static variables, like this: verb( // declared as static bool s_continue; bool Class::s_continue = true; void Class::run() { while (s_continue) handleTasks(); cleanup(); } // declared as static void signalHander(int signal); void Class::signalHandler(int signal) { s_continue = false; } ) The class tt(Signal) allows the signal handler to operate in the context of a class. The advantage of this is that static data members are no longer required and that the signal may be used to control data members of individual objects. The signal is now handled by an object, whose class must define a member verb( void signalHandler(size_t signum) override; ) and this function is responsible for handling the received signal. Since it is a member function it may affect its object's local variables and it may call its object's member functions. Static data members are not required anymore (see below for an example). Note that, as the signal may arrive at unpredicable times data members that can be modified by tt(signalHandler) should be declared using the tt(volatile) modifier. Moreover, data that can be modified by the tt(signalHandler) member and by other class members should be protected by em(mutexes) (cf. the bf(C++-11) class tt(std::mutex) or bf(pthread_mutex_lock)(3posix)). includefile(include/namespace) manpagesection(INHERITS FROM) tt(Signal) is not derived from other classes, but the classes for which signals must be handled by tt(Signal) must themselves publicly be derived from the class tt(FBB::SignalHandler) and must implement a member verb( virtual void signalHandler(size_t signum) override; ) handling the received signal. manpagesection(CONSTRUCTORS AND OVERLOADED OPERATORS) tt(Signal) is defined as a em(singleton), and does not offer public or protected constructors, nor does it offer overloaded operators. manpagesection(STATIC MEMBER FUNCTION) itemization( itb(static Signal &instance())nl() This static member can be used to access a reference to the program's single tt(Signal) object. ) manpagesection(MEMBER FUNCTIONS) All of tt(Signal)'s member functions can only be called through a reference to the program's tt(Signal) object, returning a reference to the program's single tt(Signal) object: itemization( itb(void add(size_t signum, SignalHandler &object))nl() tt(SignalHandler object) is activated on arrival of signal tt(signum). If multiple tt(SignalHandler) objects must be called then multiple tt(Signal::add) calls can be provided, and the various tt(SignalHandler::signalHandler) members are called in the same sequence as their respective tt(Signal::add) calls. If one of the earlier tt(signalHandler) members terminates the program then later tt(signalHandler) members are not activated anymore. If tt(Signal::add) is called by, e.g., an object's constructor, then its destructor should call tt(Signal::remove) to prevent the object's signal handler from being called after its destruction. itb(void remove(size_t signum, SignalHandler &object))nl() tt(SignalHandler object) for signal tt(signum) is removed from the tt(Signal) object. It is the responsibility of tt(object) to deregister itself from tt(Signal) just before tt(object) goes out of scope. Objects can only deregister themselves if they've previously registered themselves using tt(add). itb(void ignore(size_t signum))nl() Any previously installed tt(SignalHandler) object is no longer activated on arrival of signal tt(signum). In addition, if possible, signal tt(signum) is completely ignored (some signals cannot be caught, blocked, of ignored, like tt(SIGKILL) and tt(SIGSTOP) (cf. bf(signal)(7))). itb(void reset(size_t signum))nl() Any previously installed tt(SignalHandler) object is no longer activated on arrival of signal tt(signum). In addition, the default action the program takes on arrival of signal tt(signum) is reinstalled (cf. bf(signal)(7)). ) If the tt(signum) value that is passed to tt(Signal)'s members is not a defined signal value, then an bf(FBB::Exception) exception is thrown. manpagesection(EXAMPLE) verbinclude(../../signal/driver/driver.cc) manpagefiles() em(bobcat/signal) - defines the class interface manpageseealso() bf(bobcat)(7), bf(pthread_mutex_lock)(3posix), bf(signal)(7),nl() and the bf(C++-11) class tt(std::mutex). manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/tablebuf.yo0000644000175000017500000002652612222576536017711 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Table)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Construct text tables) manpagename(FBB::Table)(Generates row- or column-wise filled tables from information inserted into a std::ostream) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::Tablebuf) objects are bf(std::streambuf) objects that can be used to create tables. The tables are filled either column-wise or row-wise. Many of the table's characteristics may be fine-tuned by a separate bf(FBB::TableSupport) object, described in a separate man-page (bf(TableSupport)(3bobcat)). When no bf(FBB::TableSupport) object is used, a plain row-wise or column-wise table is constructed which can be inserted into a bf(std::ostream). Displaying a table (e.g., at the standard output stream) involves the following steps: itemization( it() Optionally, a tt(TableSupport) object is created; it() A tt(Tablebuf) object is created (maybe passing it a tt(TableSupport) object); it() The tt(Tablebuf) object is used to initialize a tt(std::ostream) it() The elements of the table are filled by inserting information into that tt(std::ostream) it() The tt(Tablebuf) itself contains the formatted table and may itself be inserted into a tt(std::ostream) like tt(std::cout). ) Tables defined by tt(TableBuf) consist of a (number of element dependent) number of rows and a fixed number of columns, the latter value is specified at construction time. Columns and rows are normally addressed using index values (starting at 0). Before the leftmost column, between the columns and beyond the last column em(separators) are defined. By default the separators are empty, but each separator may be given a (fixed) width or content. The separator before column tt(col) is addressed as separator tt(col), the rightmost separator is addressed as separator tt(nColummns). Likewise, rows can be separated from each other using separators. These separating rows are also empty by default. The row-separator before row tt(row) is addressed as row-separator tt(row). The row-separator following the final row is addressed as row-separator tt(nRows), where tt(nRows) is the value returned by the tt(nRows) member function. Non-default (i.e., non-empty) separators are defined using tt(FBB::TableSupport) objects (cf. bf(tablesupport)(3bobcat)). tt(TableBuf)'s sister-class tt(Table) can be used to insert elements into a table in a more direct way. With tt(TableBuf) em(field separators) are used to switch to the next table-element, and (with row-wise filled tables) a em(row separator) can be used to switch to the next row when it's only partially defined. Instead, with tt(Table) objects each new insertion defines another table element, and no wrapping tt(std::ostream) object is required. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) - allowing tt(TableBuf) objects to be wrapped in tt(std::ostream) objects. bf(FBB::TableBase) - This class implements common elements of the table implementation (the tt(FBB::TableBuf) class is also derived from tt(TableBase). The tt(TableBase) class is not intended to be used otherwise, and no separate man-page is provided. All facilities provided by tt(Table) inherited from tt(TableBase) are described in this man-page. manpagesection(ENUMERATIONS) The following enumerations are defined in the class bf(FBB::Tablebuf). bf(enum FillDirection)nl() This enumeration has two values: itemization( itb(ROWWISE) When this value is specified at construction time, elements are added row-wise to the table. I.e., the second element inserted into the bf(Table) will be found in the second column of the first row. itb(COLUMNWISE) When this value is specified at construction time, elements are added column-wise to the table. I.e., the second element will be found in the second row of the first column. ) bf(enum WidthType)nl() This enumeration holds two values: itemization( itb(COLUMNWIDTH) This value may be specified when the columns should be allowed variable widths. In this case each column will be as wide as its widest element. This is the default bf(WidthType) used by bf(Table) objects. itb(EQUALWIDTH) This value may be specified when all the table's columns should have equal width (i.e., equal to the width of the widest table element), ) manpagesection(CONSTRUCTORS) itemization( itb(Tablebuf(size_t nColumns, Table::FillDirection direction, Table::WidthType widthType = Table::COLUMNWIDTH)) The table's number of columns, the fill directions and the column width-type must be provided. The number of rows is implied by the combination of this parameter and the number of elements that is actually inserted into the bf(Table) object. The bf(direction) parameter specifies the way new elements are added to the bf(Table) object: row-wise or column-wise. Finally, the tt(widthType) parameter is used to specify the way the width of the table's columns is determined. Each column either defines its own width or all columns have equal widths. itb(TableBuf(TableSupport &tableSupport, Table::FillDirection direction, Table::WidthType widthType = Table::COLUMNWIDTH)) This constructor operates identically to the previous constructor, but expects an additional reference to a bf(TableSupport) object. A bf(TableSupport) object offers additional formatting features used by the table defining elements like horizontal lines between rows, additional separators, etc, etc. The bf(TableSupport) object is passed as a non-const reference as the bf(Table) object must be able to manipulate its data. See bf(tablesuppport)(3bobcat) for more information about tt(TableSupport). ) manpagesection(OVERLOADED OPERATORS) itemization( itb(std::ostream &operator<<(std::ostream &out, TableBuf &tablebuf)) This operator inserts a bf(TableBuf) into a tt(std::ostream) object. Note that the tt(TableBuf) object inserted into tt(out) is a non-const object, as the table may have to be completed by adding empty elements for missing ones. The tt(out) stream should not be equal to the tt(std::ostream) object that is used to wrap in a tt(TableBuf) object. itb(TableBuf &operator<<(TableBuf &obj, Align const &align)) This operator is used to change the default alignment of either a column or an element. It is a wrapper around the member tt(setAlign()) (see below for its description). By default, all elements are right-aligned. See bf(align)(3bobcat) for more information about the tt(Align) class. Unlike the insertion operators available for tt(Table) type objects, the insertion operator for tt(TableBuf) objects is only used to define column or cell-alignment. ) The overloaded assignment operator is not available. manpagesection(MEMBER FUNCTIONS) itemization( itb(void clear()) The contents of the table are erased. All existing elements are removed, and the table will be empty. itb(size_t nRows()) The currently available number of rows in the table is returned. Its value is only defined after calling bf(CHAR(d)ef()). itb(TableBuf &setAlign(Align const &align)) The alignment type of either a column or an element of the bf(TableBuf) object is defined using tt(setAlign). The standard alignments tt(std::left, std::right) and tt(std::internal) may be specified, but in addition the alignment tt(FBB::center) may be used if elements should be centered into their column. A construction like verb(tab << Align(2, FBB::center)) requests centering of all elements in the table's column having index value 2 (i.e., the table's 3rd column), whereas a construction like verb(tab << Align(2, 3, FBB::center)) requests centering of element [2][3]. It is the responsibility of the programmer to ensure that such elements exist. By default, all elements are right-aligned. itb(TableBuf &CHAR(d)ef()) After inserting elements into a tt(TableBuf) object its number of elements may or may not be an integral multiple of the number of columns specified at construction time. To `complete' a bf(TableBuf) object to a rectangular object, for which all column widths and alignments have been determined tt(def) may be called. It is automatically called by tt(operator<<(ostream, TableBuf)). In other situations it may be called explicitly to force the insertion of another row in a table using tt(ROWWISE) insertions. With tt(COLUMNWISE) insertions its working is complex, since new elements added to a tt(COLUMNWISE) filled table will reshuffle its elements over the table's columns. itb(setFieldSeparator(char fs)) The default field separator is the `backspace' (tt(\b)) character. After inserting a field separator the next table element will be defined. Inserting two field separators inserts an table empty element and starts the definition of the next element. This field separator character can be redefined by this function. Calling tt(setFieldSeparator) without argument disables the use of a field separator character, and only leaves the use of the tt(fs) manipulator to switch to the next field. itb(setRowSeparator(char rs)) The default row separator is the newline character (tt(\n)). After inserting a row separator the next element to enter into the table will be the leftmost element of the next row. Inserting two row separators adds an empty row to the table. Calling tt(setRowSeparator) without argument disables the use of a row separator character, and only leaves the use of the tt(rs) manipulator to switch to the next field. ) manpagesection(PROTECTED MEMBER FUNCTION) The member listed in this section implements the tasks of the comparably named virtual function in the class's private interface. This separates the redefinable interface from the user-interface. The class bf(Tablebuf) can, in accordance with Liskov's Substitution Principle, be used as a tt(std:streambuf); but it also offers a facility for classes deriving from bf(Tablebuf). This facility is listed here. itemization( itb(int pSync()) The contents of the bf(Tablebuf)'s internal buffer is flushed. ) manpagesection(MANPULATORS) itemization( itb(Table &CHAR(d)ef(Table &table)) This manipulator can be inserted into a a tt(TableBuf)'s wrapping tt(ostream) to call the table's bf(CHAR(d)ef()) member. itb(FBB::fs) This manipulator can be inserted into a tt(TableBuf)'s wrapping tt(ostream) to switch to the next field of the table. It is an alternative to using the field separator character. itb(FBB::rs) This manipulator can be inserted into a tt(TableBuf)'s wrapping tt(ostream) to switch to the next row of the table. It is an alternative to using the row separator character. ) manpagesection(EXAMPLE) verbinclude(../../tablebuf/driver/driver.cc) manpagefiles() em(bobcat/tablebuf) - defines the class interface;nl() manpageseealso() bf(bobcat)(7), bf(align)(3bobcat), bf(manipulator)(3bobcat), bf(tablelines)(3bobcat), bf(tablesupport)(3bobcat), bf(table)(3bobcat) manpagebugs() Note that tt(CHAR(d)ef()) will reshuffle elements over the table's columns when new elements are added to the table subsequent to calling tt(CHAR(d)ef()) includefile(include/trailer) bobcat-3.19.01/documentation/man/diffiehellman.yo0000644000175000017500000002334412222576536020707 0ustar frankfrankincludefile(include/header) COMMENT(replace 'classname' by the name of the new class) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::DiffieHellman)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Diffie Hellman key computations) manpagename(FBB::DiffieHellman)(Diffie-Hellman PKI, computing shared keys) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() The class bf(FBB::DiffieHellman) computes shared keys (shared secrets) using the Diffie-Hellman (1976) algorithm. The Diffie-Hellman algorithm uses public and private information. The public information consists of a em(prime) (e.g., a prime number consisting of 1024 bits), a em(generator) (for which the value 5 is commonly used), and the value tt(generator+sups(private) mod prime), where tt(private) is a randomly selected large number, which is the private information. The Diffie-Hellman algorithm is commonly used to compute a shared key which can be used to encrypt information sent between two parties. One party, which in this man-page is called the em(initiator) computes the prime and defines the generator. The prime is computed by bf(FBB::DiffieHellman)'s first constructor, while the generator is passed to this constructor as one of its arguments. For the generator the value 5 is often used. Next the initiator passes its public information, consisting of the prime, the generator, and the value tt(generator+sups(private) mod prime) to the other party, which in this man-page is called the tt(peer). The public information is written in binairy, big-endian form to file using the member tt(save). The initiator may optionally save the private information to a separate file as well. The peer thereupon receives the initiator's public information. The initialor's public information is read by a bf(FBB::DiffieHellman) constructor either expecting the name of a file or a tt(std::istream) containining the initiator's public information. Having obtained the prime and generator, the peer's public (and, optionally, private information) is saved by also calling tt(save). This results, among other things, in the value tt(generator+sups(private) mod prime), but now using the peer's private information. At this point the peer is already able to compute the shared key. The key is returned by calling the tt(key) member, which returns the shared key as a series of bytes stored in a tt(std::string). Before the initiator can compute the shared key the peer's tt(generator+sups(private) mod prime) value must be available. The peer sends the saved public data to the initiator. The initiator then passes the peer's public data either by file name or by tt(std::istream) to the tt(key) member, returning the shared key. bf(Perfect Forward Secrecy and Ephemeral Diffie Hellman) If the initiator and peer decide not to save their private information em(Perfect Forward Secrecy) and em(Ephemeral Diffie Hellman) may be obtained. Here, the procedure is applied as follows: itemization( it() Initiator and peer have agreed upon and securely exchanged a long-lasting common secret, which may be used in combination with, e.g., symmetric encryption methods. it() Applying the abovementioned procedure, the private information is never saved on file. Consequently, the shared key, once computed, cannot be reconstructed anymore. it() The value tt(generator+sups(private) mod prime) is not sent to either peer or initiator `in the clear', but encrypted using the long-lasting common secret. As the current implementation saves all public information on file, it's probably easiest to encrypt the file containing the public information. it() The recipients, having recieved the other party's encrypted public information, decrypt it using the long-lasting shared secret and compute the the shared key. it() As the secret information is not kept, the shared key cannot be reconstructed, while a Man-In-The-Middle attack is prevented by only exchanging encrypted public information. it() The shared key can now be used to encrypt a communication session ) includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(PUBLIC ENUMERATION) The enumeration tt(FBB::DiffieHellman::SecretKey) has two values: itemization( it() tt(DONT_SAVE_SECRET_KEY), indicating that the secret information should not be saved on file; it() tt(SAVE_SECRET_KEY), indicating that the secret information should be saved on file; ) manpagesection(CONSTRUCTORS) itemization( itb(DiffieHellman(size_t primeLength = 1024, size_t generator = 5, bool progress = false)) This constructor computes a prime of the specified length, and initializes the public information with the indicated generator. If tt(progress) is tt(true), the progress of the prime construction process is shown to tt(std::cout) by a series of dots, minuses and plusses. Generating a suitable prime may fail, resulting in an tt(FBB::Exception) being thrown. Unless the generator is specified as 2 or 5 the warning tt(cannot check the validity of generator ...) is inserted into the bf(mstream)(3bobcat)'s tt(wmsg) object. A warning is also inserted if the provided generator is not a generator for the computed prime. This constructor should be called by the initiator to start the Diffie-Hellman shared key computation procedure. itb(DiffieHellman(std::string const &initiatorPublicFileName)) This constructor should be called by the peer, after having received the initiator's public info. It makes the initiator's public information available to the peer, after which the peer's public and private information can be computed. itb(DiffieHellman(std::stream &initiatorPublicStream)) This constructor acts like the previous constructor, expecting a tt(std::istream) rather than a file name. It should be called by the peer, after having received the initiator's public info. It makes the initiator's public information available to the peer, after which the peer's public and private information can be computed. itb(DiffieHellman(std::string const &initiatorPublicFileName, std::string const &initiatorPrivateFileName)) Unless the initiator's tt(DiffieHellman) object is still available, this constructor should again be called by the initiator, to load the initiator's public and private data. itb(DiffieHellman(std::stream &initiatorPublicStream, std::stream &initiatorPrivateStream)) This constructor acts like the previous constructor, expecting tt(std::istreams) rather than file names. It should be called by the initiator, to load the initiator's public and private info. ) Copy and move constructors are available. manpagesection(OVERLOADED OPERATORS) Copy and move assignment operators are available. manpagesection(MEMBER FUNCTIONS) itemization( itb(std::string key() const) This member should be called by the peer. It returns the shared key. If the key cannot be computed, or if the key is not resistant to the small group attack (i.e., if the key equals 1, or is at least equal to the public prime value, or if tt(key+sups((prime - 1) / 2) mod prime != 1)), then an tt(FBB::Exception) is thrown. itb(std::string key(std::string const &peerPublicFileName) const) This member should be called by the initiator. It skips the data referring to the prime and generator found in tt(peerPublicFileName) and then reads the peer's tt(generator+sups(private) mod prime) value. If this value cannot be read or if the key is not resistant to the small group attack (cf. the description of the previous tt(key) member) then an tt(FBB::Exception) is thrown. It returns the shared key. itb(std::string key(std::istream const &peerPublicStream) const) This member should be called by the initiator. It acts like the previous tt(key) member, reading the peer's tt(generator+sups(private) mod prime) value from tt(peerPublicStream). It returns the shared key. itb(void save(std::string const &basename, SecretKey action = DONT_SAVE_SECRET_KEY)) This member should be called by the initiator. It saves the public information on the file tt('basename'.pub). The information is written in binary, big-endian format, using the following organization: - the size of the prime in bytes;nl() - the prime's bytes;nl() - the size of the generator in bytes;nl() - the generator's bytes;nl() - the size of the public info (tt(generator+sups(private) mod prime)) in bytes;nl() - the public info's bytes.nl() If tt(action) is specified as tt(SAVE_SECRET_KEY) then the private information is written in binary, big-endian format, using the following organization: - the size of the private information in bytes;nl() - the private information bytes. ) manpagesection(EXAMPLE) When called without arguments, the example program generates Diffie-Hellman parameters writing the initiator's public and private information to, respectively, tt(init.pub) and tt(init.sec). When called with one argument, tt(init.pub) is read, and the peer's public and private information is written to, respectively, tt(peer.pub) and tt(peer.sec). Next, the (peer's) shared key is written to tt(peerkey). When called with two arguments, tt(init.pub) and tt(init.sec) are read, as well as the peer's public information (on the file tt(peer.pub)). Next, the (initiator's) shared key is written to tt(initkey). The files tt(peerkey) and tt(initkey) should be identical. verbinclude(../../diffiehellman/driver/driver.cc) manpagefiles() em(bobcat/diffiehellman) - defines the class interface manpageseealso() bf(bobcat)(7), bf(bigint)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/binarysearch.yo0000644000175000017500000000702312222576536020566 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::binary_search)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz) (Binary search function) manpagename(FBB::binary_search)(Extensions to the STL binary_search function template) manpagesynopsis() bf(#include )nl() manpagedescription() The bf(FBB::binary_search) function templates extend the STL tt(binary_search) function template returning an iterator to the element found, instead of a bf(bool) value informing the caller whether or not the searched for element is present in a provided iterator range. The bf(bool) value returned by the STL tt(binary_search) function template is often not the kind of information the caller of the function is interested in. Rather, the caller will often want to use tt(binary_search) in the way tt(find_if) is used: returning an iterator to the found element or returning the end-iterator if the element was not found. Whereas tt(find_if) does not require the elements in the iterator range to be sorted, and thus will use a linear search tt(binary_search) may use the sorted nature of the elements to its advantage, using a binary search algorithm requiring tt(2 log N) iterations to locate the searched for element rather than (on average) tt(N/2) iterations. The tt(FBB::binary_search) algorithm uses this binary searching process while at the same time allowing its use like tt(find_if). Since the tt(FBB::binary_search) function templates use the same number and types of parameters as the tt(stl::binary_search) function templates the explicit use of the tt(FBB) namespace will often be required in situations where both function templates are made available to the compiler. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(OVERLOADED FUNCTIONS) In the following description several template type parameters are used. They are: itemization( it() bf(Iterator) represents an iterator type; it() bf(Type) represents a value of the type to which tt(Iterator) points. it() bf(Comparator) represents a comparator function or class type object which was used to sort the elements to which the tt(Iterator) range refer; ) itemization( itb(Iterator binary_search(Iterator begin, Iterator end, Type const &value)) Using a binary search algorithm tt(value) is searched for in the range of elements referred to by the provided iterator range. If the value is found an iterator pointing to this value is returned, otherwise tt(end) is returned. The elements in the range must have been sorted by the tt(Type::operator<()) function. itb(Iterator binary_search(Iterator begin, Iterator end, Type const &value, Comparator comparator)) Using a binary search algorithm tt(value) is searched for in the range of elements referred to by the provided iterator range. If the value is found an iterator pointing to this value is returned, otherwise tt(end) is returned. The elements and the provided value are compared using tt(comparator(*iterator, value)) calls, where tt(*iterator) refers to an object in the provided iterator range. The elements in the range must have been sorted by the tt(Comparator) function or function object. ) manpagesection(EXAMPLES) verbinclude(../../binarysearch/driver/driver.cc) manpagefiles() em(bobcat/binarysearch) - defines the template functions manpageseealso() bf(bobcat)(7) manpagebugs() None reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/onekey.yo0000644000175000017500000000556112222576536017413 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::OneKey)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (One keystroke input) manpagename(FBB::OneKey)(Single keystroke input, not requiring `Return') manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(OneKey) objects may be used to realize `direct keyboard input': a pressed key becomes available without the need for pressing tt(Enter). The characters are obtained from the standard input stream. Direct key entry remains in effect for as long as the bf(OneKey) object exists. Once the object is destroyed the standard input stream will return to its default mode of operation, in which input is `confirmed' by a newline character. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ENUMERATION) The bf(OneKey::Mode) enumeration is used to control echoing of returned characters. It has two values: itemization( it() bf(OFF): returned characters are em(not) echoed to the standard output stream; it() bf(ON): returned characters em(are) echoed to the standard output stream. ) manpagesection(CONSTRUCTORS) itemization( itb(OneKey(OneKey::Mode state = OneKey::OFF)) This constructor initializes the bf(OneKey) input object. By default, entered characters are not echoed. By constructing the object with the bf(OneKey::ON) argument, entered characters are echoed to the standard output stream. This construct throws an tt(Exception) exception if it not properly complete. The constructor may fail for the following reasons: itemization( it() the standard input stream is not a tty (e.g., when the standard input stream is redirected to a file); it() the current state of the standard input stream can't be determined; it() the standard input stream's state can't be changed to the `direct keyboard input' mode. ) ) The copy constructor (and the overloaded assignement operator) are not available. manpagesection(MEMBER FUNCTIONS) itemization( itb(int get() const) Returns the next character from the standard input stream, without the need for pressing tt(Enter). itb(void setEcho(OneKey::Mode state)) Changes the echo-state of the bf(OneKey) object. The argument may be either bf(OneKey::ON) or bf(OneKey::OFF). itb(void verify() const) Obsoleted, will be removed in a future Bobcat release. ) manpagesection(EXAMPLE) verbinclude(../../onekey/driver/driver.cc) manpagefiles() em(bobcat/onekey) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/manipulators.yo0000644000175000017500000000707312257021317020625 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Manipulators)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz)(Manipulators) manpagename(FBB::Manipulators)(Manipulators defined in the FBB namespace) manpagedescription() Various manipulators are defined within the bf(FBB) namespace. This manual page provides an overview of the manipulators that are currently defined in the bf(FBB) namespace. manpagesection(MANIPULATORS) itemization( itb(FBB::center) defined in tt(bobcat/align) This manipulator can be specified when constructing an bf(FBB::Align) object to indicate that a table column should center its contents. itb(FBB::decindent) defined in tt(bobcat/indent) This manipulator reduces the indentation level. itb(FBB::def) defined in tt(bobcat/table) This manipulator `completes' a bf(Table) object to a full rectangular object. It can be inserted into a bf(Table) object. itb(FBB::err) defined in tt(bobcat/msg) Generates an error message. itb(FBB::fatal) defined in tt(bobcat/msg) Generates a fatal message, followed by an bf(Exception)bf((1)) exception. itb(FBB::fs) defined in tt(bobcat/tablebuf) Starts the definition of the next element in a table. itb(FBB::info) defined in tt(bobcat/msg) Generates an informational message. itb(FBB::incindent) defined in tt(bobcat/indent) This manipulator will increment the indentation level. itb(FBB::indent) defined in tt(bobcat/indent) This manipulator inserts the currently defined number of indentation blanks into an tt(ostream). itb(FBB::indentdec) defined in tt(bobcat/indent) This manipulator will insert, then reduce the indentation level. itb(FBB::indentinc) defined in tt(bobcat/indent) This manipulator will insert, then increment the indentation level. itb(FBB::insertable) defined in tt(bobcat/errno) OBSOLETED, no required anymore.nl() Allows insertions into just constructed anonymous bf(FBB::Exception) objects. itb(FBB::lm) defined in tt(bobcat/ofoldstreambuf) This manipulator sets the left margin of bf(FBB::OFoldStream) objects. itb(FBB::mlm) defined in tt(bobcat/ofoldstreambuf) This manipulator modifies (alters) the left margin of bf(FBB::OFoldStream) objects. itb(FBB::nlindent) defined in tt(bobcat/indent) This manipulator will insert a newline, then indent. itb(FBB::rs) defined in tt(bobcat/tablebuf) Starts the definition of the next row in a table. itb(FBB::spool) defined in tt(bobcat/msg) Generates a (partial) informational message. itb(FBB::errnodescr) defined in tt(bobcat/exception) Inserts the textual description of the current tt(::errno) value into the tt(ostream) into which the manipulator is inserted. If tt(errno == 0) nothing is inserted. itb(FBB::throwable) defined in tt(bobcat/errno) OBSOLETED, no required anymore.nl() Allows an bf(FBB::Exception) object to be thrown as an exception following a series of insertions. itb(FBB::warning) defined in tt(bobcat/msg) Generates a warning message. ) manpageseealso() bf(bobcat)(7), bf(columnwidth)(3bobcat), bf(equalwidth)(3bobcat), bf(errno)(3bobcat), COMMENT( OBSOLETED, to remove in some future version ) bf(indent)(3bobcat), bf(lm)(3bobcat), bf(mlm)(3bobcat), bf(msg)(3bobcat), bf(table)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/primefactors.yo0000644000175000017500000001471312257522663020616 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::PrimeFactors)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz)(Prime Factorization) manpagename(FBB::PrimeFactors)(Performs the prime-number factorization of (BigInt) values) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() Integral values fall into two categories: prime numbers, whose only integral divisors are their own values and 1, and composite numbers, which also have at least one other (prime number) integral divisor. All composite integral values can be factorized as the product of prime numbers. E.g., 6 can be factorized as 2 * 3; 8 can be factorized as 2 * 2 * 2. Finding these prime factors is called the prime number factorization, or `prime factorization'. When factorizing a value its prime factors may sometimes repeatedly be used as integral divisors: 8 is factorized as tt(pow(2, 3)), and 36 is factorized as verb 36 = pow(2, 2) * pow(3, 2) ) The class bf(FBB::PrimeFactors) performs prime number factorizations of tt(FBB::BigInt) values. When factorizing a value prime numbers up to tt(sqrt(value)) must be available, as prime numbers up to tt(sqrt(value)) may be factors of tt(value). Currently tt(PrimeFactors) uses the sieve of Eratosthenes to find these prime numbers. To find the next prime number beyond tt(lastPrime), the sieve of Eratosthenes must be used repeatedly for tt(lastPrime += 2) until tt(lastPrime) is prime. Once determined, prime numbers can of course be used directly to determine the next prime number or to factorize an integral value. To accellerate prime number factorization and Eratosthenes's sieve bf(PrimeFactors) saves all its computed prime numbers in either a tt(std::vector) or in a file. Once determined, these prime numbers may again be used when factorizing the next integral value. After factorizing an integral value its prime number factors and associated powers are made available in a vector of (tt(PrimeFactors::PrimePower)) structs, containing the value's sorted prime factors and associated powers. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(TYPEDEFS AND ENUMS) itemization( itb(struct PrimePower) contains two fields: verb( struct PrimePower { BigInt prime; size_t power; }; ) Here, tt(power) represents the number of times tt(prime) can be used as an integral divisor of the value that was factorized by bf(PrimeFactors). itb(Factors) is a synonym for tt(std::vector)nl() Linking option: tt(-lbobcat) manpagedescription() Objects of this class implement a tt(std::streambuf) class that are used to handle messages in a standardized way. Messages may be prefixed with order numbers and labels and/or line numbers. By default all messages are inserted into the standard output stream, but other destinations (standard error, a named file, etc.) can easily be configured. bf(FBB::Mbuf) objects themselves are tt(std::streambuf) objects, so they can be used to construct tt(std::ostream) objects. However, they are intended to be used by bf(mstream)(3bobcat) objects. manpagesection(NAMESPACE) bf(FBB)nl() All elements mentioned in this man-page, are defined in the namespace bf(FBB). manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(CONSTRUCTORS) itemization( itb(Mbuf()) The default constructor handles messages using the tt(std::streambuf) also used by tt(std::cout). There is no limit to the number of messages that may be inserted. No message or line numbers are shown, no exception are thrown when inserting messages. itb(explicit Mbuf(std::streambuf *buf, size_t maxCount = std::numeric_limits::max(), std::string const &tag = "", bool throwing = false)) This constructor uses tt(buf) to handle messages. By default (using the default argument values) there is no limit to the number of messages that may be inserted. No message or line numbers are shown, no exception are thrown when inserting messages. Specifying any other value than tt(std::numeric_limits::max()) sets the maximum number of messages that can be inserted to that value. The tt(tag) defines the text of the message label (e.g., tt(Error)). When tt(throwing) is specified as tt(true) an tt(FBB::Exception) exception is thrown after completing a message. The generated exception holds the id (see below for the member tt(id)) of the bf(FBB::Mbuf) object from which the exception was thrown as well as the text tt(FBB::Mbuf). itb(explicit Mbuf(std::string const &name, size_t maxCount = std::numeric_limits::max(), std::string const &tag = "", bool throwing = false)) This constructor creates a tt(std::ofstream) from the provided tt(name) parameter that receives the messages handled by the constructed bf(FBB:Mbuf) object. It throws an tt(FBB::Exception) exception if the stream cannot be opened for writing. If a file by that name already exists it is rewritten. The remaining parameters are identical to those of the previous two constructors. ) As bf(FBB::Mbuf) inherits from tt(std::streambuf) the copy constructor is not available. Neither is the move constructor. manpagesection(MEMBER FUNCTIONS) itemization( itb(size_t count() const) returns the number of inserted messages (if tt(setCount) has been called: the value set by the last tt(setCount) call plus the number of inserted messages since that call). itb(bool lineExcess() const) returns bf(true) after attempting to insert an additional message after tt(maxCount()) number of messages have been inserted. itb(std::string const &lineTag() const) returns the currently used line-tag (by default `tt(Line)'). itb(size_t maxCount() const) returns the maximum number of messages that can be inserted. If the returned value equals tt(std::numeric_limits::max()) then there is no limit to the number of messages that can be inserted. itb(void noLineNr()) calling this member will suppress the display of a line number if it is called after calling tt(setLineNr) (see below) but before a message is being (or has been) inserted. itb(void reset(std::streambuf *buf, size_t maxCount, std::string const &tag, bool throwing)) messages inserted into bf(FBB::Mbuf) objects are handled by tt(std::streambuf buf). By specifying tt(std::numeric_limits::max()) for tt(maxCount) there is no limit to the number of messages that may be handled by this tt(std::streambuf). The tt(tag) defines the text of the message label (e.g., tt(Error) or the empty string for no message label). When tt(throwing) is specified as tt(true) an tt(FBB::Exception) exception is thrown after completing a message. itb(void reset(std::string const &name, size_t maxCount, std::string const &tag, bool throwing)) messages inserted into bf(FBB::Mbuf) objects are handled by a tt(std::ofstream) created using the provided tt(name) parameter. It throws an tt(FBB::Exception) exception if the stream cannot be opened for writing. If a file by that name already exists it is rewritten. The remaining parameters are identical to those of the previous tt(reset) members. itb(void reset(FBB::Mbuf const &mbuf)) the current object is reset using the parameters of the tt(mbuf) parameter. Following the reset all of the current object's parameters can independently be modified from those used by tt(mbuf). itb(void setCount(size_t count)) assigns the value tt(count) to the object's message counter. itb(void setLineNr(size_t lineNr)) specifies the value tt(lineNr) as the message's line number when the next line is displayed (see also tt(noLineNr)). This value is em(not) changed by the bf(FBB::Mbuf) object. To display another line number the member will have to be called again (i.e., the line number is not displayed automatically again at every new line). itb(void setLineTag(std::string const &tag)) specifies the tag prefixing line numbers. By default the line tag equals `tt(Line)'. itb(void setMaxCount(size_t maxCount)) defines tt(maxCount) as the maximum number of messages that can be inserted into the bf(FBB::Mbuf) object. itb(void setTag(std::string const &tag)) specifies the tag prefixing messages. By default the tag is empty. If not empty the tag is enclosed by square brackets. E.g., specifying the tag `tt(Error)' will prefix messages with tt([Error]). itb(std::string const &tag() const) returns the currently used message tag (by default an empty string). itb(bool throws()) returns tt(true) when the bf(FBB::Mbuf) object will throw an tt(FBB::Exception) exception at the next completed message. The generated exception holds the id (see earlier for the member tt(id)) of the bf(FBB::Mbuf) object from which the exception was thrown as well as the text tt(FBB::Mbuf). itb(void throwing(bool ifTrue)) modifies the behavior of bf(FBB::Mbuf) objects at completed messages. After passing tt(true) bf(FBB::Mbuf) objects will throw an tt(FBB::Exception) exception at the next completed message, otherwise this exception is not thrown. ) manpagesection(EXAMPLE) See the bf(mstream)(3bobcat) example. manpagefiles() em(bobcat/mbuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(errno)(3bobcat), bf(mstream)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/tablesupport.yo0000644000175000017500000003051412222576536020641 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::TableSupport)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz)(Table Support Base class) manpagename(FBB::TableSupport)(Defines protocols for Table-support classes) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() This class is designed as a (non-pure) base class for objects handling some of the functionality of tt(FBB::Table) and tt(FBB::TableBuf) objects. By overriding its virtual functions users have control over the way the actual layout of tables is defined. By default the virtual members of this class do not separate the columns of the table from each other The Bobcat library offers the specialized class tt(TableLines) extending the basic facilities of tt(TableSupport) by allowing rows to be separated from each other by (partial) horizontal lines (see the bf(tablelines)(3bobcat) man-page for a description). When more specialized handling is required a class should be derived from bf(FBB::TableSupport) overriding those members that violate the programmer's current intentions. An object of this derived class may be presented to a tt(FBB::Table) or tt(FBB::TableBuf) constructor, to activate the special handling. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ENUMERATION) The enum tt(ColumnType) defines the following values (see also the description of the tt(struct HLine), below): itemization( itb(SKIP) a section of a row-separating line should remain empty. This value is normally not used by applications; itb(USE) a section of a row-separating line should be used (e.g., by writing a (horizontal) line); itb(LEFT_FULL) a (horizontal) line should be written over the total width of the separator to the left of a series of columns itb(RIGHT_FULL) a (horizontal) line should be written over the total width of the separator to the right of a series of columns; itb(LEFT_MID) a (horizontal) line should be written over the right-half part of the width of the separator to the left of a series of columns; the left-hand part remains blank; itb(RIGHT_MID) a (horizontal) line should be written over the left-half part of the width of the separator to the right of a series of columns; the right-hand part remains blank; ) The value tt(SKIP) should always be used by itself; remaining values of the enum may be combined using the binary or (tt(|)) operator. manpagesection(PUBLIC TYPE) itemization( itb(struct HLine) This struct has the following fields: verb( size_t d_row; size_t d_begin; size_t d_end; size_t d_type; ) It offers two constructors: itemization( itb(HLine(size_t row, size_t begin, size_t end)) itb(HLine(ColumnType type, size_t row, size_t begin, size_t end)) ) Objects of type bf(TableSupport::HLine) may be inserted into a bf(TableSupport) object to indicate section(s) of a horizontal separator between table rows that should be displayed or skipped. E.g., to specify that a separator should be written in row 1 between columns 2 up to (not including) 5, extending the separator to the left by half the width of the separator between columns 1 and 2 and to the right by the full width of the separator between columns 4 and 5 the following tt(HLine) object should be inserted into the tt(TableSupport ts) object: verb(ts << HLine(LEFT_MID | RIGHT_FULL, 1, 2, 5);) Multiple tt(HLine) objects may be inserted into a tt(TableSupport) object, their ordering is irrelevant. When colum ranges overlap then their tt(ColumType)s are merged. ) manpagesection(PROTECTED TYPES) itemization( itb(const_iterator) This type is defined in the class's protected section. bf(TableSupport::const_iterator) is an input-iterator returning pointers to bf(struct Field) (see below) objects for table columns and column separators (see below at the tt(begin) and tt(end) members) itb(struct Field) This type has two data members: tt(width) and tt(type), representing, respectively, the width and tt(ColumnType) of a column or separating column. Although column types can be combined when inserting them using tt(HLine) objects, tt(type) values of tt(Field) objects returned by tt(TableSupport) members only contain single values (like tt(SKIP) or tt(LEFT_MID)). ) manpagesection(CONSTRUCTORS) The default, copy and move constructors are available. manpagesection(OVERLOADED OPERATORS) itemization( itb(TableSupport &operator<<(TableSupport &support, size_t width)) This operator defines a column-separator of tt(width) space characters. The argument tt(width) may be zero, in which case no visible separator is used. The first separator inserted refers to the separator to the left of the table's leftmost column. Subsequent separators separate subsequent columns. At most tt(nColumns + 1) separators can sensibly be inserted. Additional separators are ignored when a table is inserted into an tt(ostream). itb(TableSupport &operator<<(TableSupport &support, std::string const &sep)) This operator defines a separator as a piece of text. The string may be empty, in which case no visible separator is inserted into the table. The first separator inserted refers to the separator to the left of the table's leftmost column. Subsequent separators separate subsequent columns. Textual and numeric separator may be intermixed. At most tt(nColumns + 1) separators can sensibly be inserted. Additional separators are ignored when a table is inserted into an tt(ostream). itb(TableSupport &operator<<(TableSupport &support, HLine const &hsep)) This operator defines how a section of a horizontal separator of a specified row should be displayed (see the description of tt(ColumnType) in the tt(ENUMERATION) section). ) The overloaded copy and move assignment operators are available. manpagesection(PUBLIC MEMBER FUNCTIONS) itemization( itb(void hline(size_t row) const) When inserting a table into a tt(std::ostream) tt(Table) and tt(TableBuf) objects call this member just before the indicated row (offset) is inserted into a tt(std::ostream). It calls tt(v_hline), passing it tt(row). itb(void hline() const) When inserting a table into a tt(std::ostream) tt(Table) and tt(TableBuf) objects call this member just after inserting the table's final row. It calls tt(v_hline) without arguments. itb(void setParam(std::ostream &ostr, size_t nRows, size_t nColumns, std::vector const &align)) This member provides the bf(TableSupport) object with values that are essential for its proper functioning. It is called from the tt(Table) and tt(TableBuf)'s tt(def) member or manipulator. A tt(TableSupport) object can be used before that to specify widths and types of separators, though. This member's parameters are initialized by the tt(Table) and tt(TableBuf) class objects as follows:nl() bf(ostr) is a reference to the bf(std::ostream) into which the table will be inserted; nl() bf(nRows) specifies the number of rows used by the table;nl() bf(nColumns) specifies the number of columns if the table;nl() bf(align) is a reference to a constant vector of (column) alignment specifications. itb(void vline(size_t col) const) When inserting the data elements of the rows of a table into a tt(std::ostream) tt(Table) and tt(TableBuf) objects call this member just before inserting the data elements of column tt(col). Its intended task is to write a column separator just before the data elements themselves. It calls tt(v_vline) passing it its tt(col) parameter. itb(virtual void vline() const) When inserting a table into a tt(std::ostream) tt(Table) and tt(TableBuf) objects call this member after inserting the data elements of the rows of the table. It is called at the end of each row. It calls tt(v_vline) without arguments. itb(size_t width() const) Returns the total width of the table. ) manpagesection(PROTECTED MEMBER FUNCTIONS) The following members are available to classes derived from bf(TableSupport). Except for tt(sep) and tt(sepWidth) their values are only defined after tt(setParam) has been called. This latter function is called from the tt(def) member or manipulator of tt(Table) or tt(TableBuf) objects. itemization( itb(std::vector const &align() const) A reference to a vector of tt(Align) objects, defining the alignments and widths of the table's columns is returned. itb(const_iterator begin(size_t row) const) An iterator returning information about the first column element when displaying the horizontal separator preceding line tt(row) is returned. To obtain the information about the separator beyond the last row tt(nRows()) should be used as its argument. The `column elements' of the table are its separators and data columns. Dereferencing the returned tt(const_iterator) provides access to a tt(Field) struct defining the type and width of a column element. Dereferencing the iterator returned by tt(begin) provides information about the leftmost column separator. By incrementing the iterator all subsequent column elements are visited. The iterator's value becomes undefined once it reaches the value returned by tt(end) (see below). itb(size_t colWidth(size_t col) const) The width of the indicated column is returned. itb(const_iterator end(size_t row) const) An iterator indicating the end of the iterator range starting at tt(begin(row)) is returned. itb(size_t nColumns() const) The number of columns of the table is returned. itb(size_t nRows() const) The number of rows of the table is returned. itb(std::ostream &out() const) A reference to the stream into which the table is inserted is returned. itb(std::vector const &sep()) A reference to the separators that are defined for the table's columns is returned. Element tt(col) refers to the separator to the left of the table column tt(col), element tt(nColumns()) refers to the separator to the right of the rightmost table column. itb(size_t sepWidth(size_t col) const) The width of the indicated separator is returned. Element tt(col) refers to the separator to the left of the table column tt(col), element tt(nColumns()) refers to the separator to the right of the rightmost table column. ) manpagesection(VIRTUAL MEMBER FUNCTIONS) The following member functions can be overridden by derived classes to redefine the way horizontal and vertical separators are displayed. itemization( itb(virtual void v_hline(size_t row) const) This member is called from tt(hline(size_t row)), receiving its tt(row) parameter. Its task is to write a horizonal separator for row tt(row). By default nothing is inserted. It may do so by iterating over the range defined by the tt(begin) and tt(end) members, deciding what to do on the basis of the tt(Field) objects referred to by the iterators. itb(virtual void v_hline() const) This member is called from tt(hline()). Its intended task is to write a (partial) horizontal line beyond the table's last line of data elements. By default it calls tt(hline(nRows)). itb(virtual void v_vline(size_t col) const) This member is called from tt(vline(size_t col)), receiving its tt(col) parameter. Its task is to write a separator before data column tt(col). By default it inserts tt(separator[col]) if if is available. If that separator is not defined, no action is performed. itb(virtual void v_vline() const) This member is called from tt(vline()). Its intended task is to write a column separator, terminating a line of the table. By default it inserts a new-line (tt(\n)) character. ) manpagesection(EXAMPLE) See the example in the bf(table)(3bobcat) man-page. manpagefiles() em(bobcat/tableSupport) - defines the class interface manpageseealso() bf(bobcat)(7), bf(align)(3bobcat), bf(table)(3bobcat), bf(tablebuf)(3bobcat), bf(tablelines)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/user.yo0000644000175000017500000000533412222576536017075 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::User)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (/etc/passwd user info) manpagename(FBB::User)(Provides the tt(/etc/passwd) info of the current user) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() This class retrieves the information of the current user from the information in tt(/etc/passwd). The class is a simple wrapper class around the bf(getpwent)(3) function. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) itemization( itb(User()) The default constructor determines the current user's data. This constructor throws an tt(Exception) exception if it did not properly complete because the current user name could not be found in tt(/etc/passwd). ) The copy and move constructors are available. manpagesection(OVERLOADED OPERATORS) The copy and move assignment operators are available. manpagesection(MEMBER FUNCTIONS) itemization( itb(size_t eGroupid() const) Returns the user's tt(effective) group-id. itb(size_t eUserid() const) Returns the user's tt(effective) user-id. itb(size_t groupid() const) Returns the user's group-id. itb(std::string homedir() const) Returns the user's home directory (including a trailing tt(/)). itb(bool inGroup(size_t gid, bool useEffective = true) const) Returns tt(true) if the current user is a member of group tt(gid), otherwise tt(false) is returned. The user's effective group id is also checked if tt(useEffective) is specified as tt(true) (which is provided as default function argument). itb(std::string name() const) Returns the user's user-name. itb(std::string password() const) Returns the user's encrypted password. But see also the bf(BUGS) \ section. itb(std::string realname() const) Returns the user's real name, as listed in the tt(/etc/passwd)'s \ em(gecos) field. itb(std::string shell() const) Returns the user's shell. itb(size_t userid() const) Returns the user's user-id. ) manpagesection(EXAMPLE) verbinclude(../../user/driver/driver.cc) manpagefiles() em(bobcat/user) - defines the class interface manpageseealso() bf(bobcat)(7), bf(getpwent)(3) manpagebugs() If the user is a member of multiple groups, only the group id listed in tt(/etc/passwd) is returned by bf(groupid()). If shadow passwording is used, the string returned by bf(password()) will probably not contain the encrypted password. includefile(include/trailer) bobcat-3.19.01/documentation/man/iostreambuf.yo0000644000175000017500000001130012241665740020422 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::IOStreambuf)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Streambuf doing I/O) manpagename(FBB::IOStreambuf)(streambuf allowing input and output operations) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() This class implements a specialization of the bf(std::streambuf) class, allowing input operations from and output operations to different files. It is intended to be used in combination with bf(FBB::IOStream), thus allowing all stream-based input and output operations using the same object without the need to use em(seek)-operations. Using an bf(FBB::IOStream) object it is, e.g., possible to construct two-way communications using pipes, much like the facilities offered by sockets. If the streams that will be associated with the bf(IOStreambuf) object support seeking, then the bf(IOStreambuf) will do so to. Seeking might also be availble for a single stream (either the bf(std::istream) or the bf(std::ostream)). When the bf(IOStreambuf) object goes out of scope, its associated bf(std::ostream) object is flushed. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(CONSTRUCTORS) itemization( itb(IOStreambuf()) The default constructor results in a bf(IOStreambuf) object that cannot be immediately used. Its member bf(open()) must be called first. itb(IOStreambuf(std::istream &in, std::ostream &out)) This constructor associates the bf(IOStreambuf) object with a bf(std::istream) and a bf(std::ostream). All output operations will be passed on to the bf(std::ostream), all input operations to the bf(std::istream). The streams passed to bf(IOStreambuf()) should outlive the bf(IOStreambuf) object. ) Copy and move constructors is not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::IOStreambuf) inherits from these classes. itemization( itb(void open(std::istream &in, std::ostream &out)) This member (re)associates the bf(IOStreambuf) object with a bf(std::istream) and a bf(std::ostream). All output operations will be passed on to the bf(std::ostream), all input operations to the bf(std::istream). The streams passed to bf(IOStreambuf()) should outlive the bf(IOStreambuf) object. If this member is called for an bf(IOStreambuf) object already associated with an bf(std::ostream) object, the already associated bf(std::ostream) object is flushed before setting up the new association. ) manpagesection(VIRTUAL PROTECTED MEMBER FUNCTIONS) The following bf(std::streambuf) member functions should only be called when the bf(FBB::Streambuf) object is associated with bf(std::istream) and bf(std::ostream) objects (i.e., they should not be called between the construction of a default bf(FBB:IOStreambuf) object and a subsequent call of bf(IOStreambuf::open())): The members listed in this section implement the tasks of comparably named virtual function in the class's private interface. This separates the redefinable interface from the user-interface. The class bf(IOStreamBuf) can, in accordance with Liskov's Substitution Principle, be used as a tt(std:streambuf); but it also offers facilities for classes deriving from bf(IOStreamBuf). These facilities are listed here. itemization( itb(pos_type pSeekoff(off_type offset, std::ios::seekdir way, std::ios::openmode mode = std::ios::in | std::ios::out)) With seekable streams, repositions the associated bf(std::istream) or bf(std::ostream) is repositioned to offset tt(offset), relative to tt(way). itb(pos_type pSeekpos(off_type offset, std::ios::openmode mode = std::ios::in | std::ios::out)) With seekable streams, repositions the associated bf(std::istream) or bf(std::ostream) is repositioned to offset tt(offset), relative to the beginning of the stream. itb(int pSync()) This member flushes the associated bf(std::ostream) object. itb(std::streamsize pXsputn(char const *buffer, std::streamsize n)) This member inserts tt(n) characters from tt(buffer) into the associated bf(std::ostream) stream. ) manpagesection(EXAMPLE) See the example provided with bf(process)(3bobcat). manpagefiles() em(bobcat/iostreambuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(iostream)(3bobcat), bf(process)(3bobcat) manpagebugs() None reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/pipe.yo0000644000175000017500000001576312257021365017054 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Pipe)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (System Level Communication Pipe) manpagename(FBB::Pipe)(Defines a system level communication pipe) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::Pipe) objects may be used to construct a em(pipe). tt(Pipe) objects offer a simple interface to the reading and writing ends of pipes. tt(Pipe) objects are object-wrappers around the bf(pipe)(2) system call. A tt(Pipe) which is created just before a program forks can be used to set up a line of communication between the parent and child process. Information which is written by the child process to its standard output stream can be redirected to the writing end of the pipe (using the tt(writtenBy) member). The information appearing at the reading end of the pipe can then be extracted using, e.g., an tt(IFdStream) object, initialized with the tt(Pipe)'s reading file descriptor, or the reading end of the pipe can be redirected to an existing stream whose file descriptor is known, like tt(cin) (which uses the tt(STDIN_FILENO) file descriptor). When a tt(Pipe) object goes out of scope, no bf(close)(2) operation is performed on the pipe's file descriptors. After setting up the pipe using the tt(Pipe's) member functions and passing the tt(Pipe's) file descriptors to code that uses the tt(Pipe's) descriptors, the tt(Pipe) object could in fact safely be destroyed. If the pipe should be closed at destruction time, a class could be derived from bf(Pipe)(3bobcat), whose destructor performs the required closing-operation. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) itemization( itb(Pipe()) The default tt(Pipe) constructor constructs a basic pipe, calling bf(pipe)(2). This constructor throws an tt(Exception) exception if the default tt(Pipe) constructor did not properly complete. The thrown bf(Exception) object's tt(which()) member shows the system's tt(errno) value set by the failing bf(pipe)(2) function. itb(Pipe(int const *fd)) This constructor expects two file descriptors, which already define a pipe, stored at tt(fd). Following the construction of the tt(Pipe) object the array at by tt(fd) is no longer used by the tt(Pipe) object. ) The copy constructor is available. manpagesection(MEMBER FUNCTIONS) itemization( itb(int readFd() const) Returns the pipe's file descriptor that is used for reading itb(void readFrom(int filedescriptor)) Sets up redirection from the internal em(read) filedescriptor to the given filedescriptor: information written to the write-end of the pipe may be retrieved by extracting the information from the stream that is associated with the indicated file descriptor. E.g., after the call tt(readFrom(STDIN_FILENO)) information inserted into the write-end of the pipe can be retrieved from tt(cin). itb(void readFrom(int const *filedescriptors, size_t n)) Sets up redirection from the internal em(read) filedescriptor to the given filedescriptors: information is read from the tt(Pipe) object when reading from any of the bf(n) provided filedescriptors (experimental). itb(int readOnly()) Closes the writing end of the pipe, returns the reading end's file descriptor. This member can be used, e.g., to construct an tt(IFdStream) object to extract the information that is inserted into the write-end of the pipe. itb(void verify() const) Obsoleted, can safely be removed from source files. itb(int writeFd() const) Returns the pipe's file descriptor that is used for writing. itb(void writtenBy(int filedescriptor)) Sets up redirection from the internal em(write) filedescriptor to the given filedescriptor: information is written to the tt(Pipe) object when writing to the provided filedescriptor. E.g., after the call tt(writtenBy(STDOUT_FILENO)) information sent to the standard output stream (by either tt(cout) or by a child process (cf. bf(exec)(3))) is inserted into the write-end of the pipe. itb(void writtenBy(int const *filedescriptors, size_t n)) Sets up redirection from the internal em(write) filedescriptor to the given filedescriptors: information is inserted into the write-end of the tt(Pipe) object when writing to each of the bf(n) provided filedescriptors. E.g., when passing an array of two tt(int) values, respectively equal to tt(STDOUT_FILENO) and tt(STDERR_FILENO) to this member, all information which is thereafter sent to the standard output or error streams is inserted into the write-end of the pipe. itb(int writeOnly()) Closes the reading end of the pipe, returns the writing end's file descriptor. ) manpagesection(PROTECTED ENUMERATION) The bf(RW) protected enumeration has the following elements: itemization( itb(READ) The index in bf(d_fd[]) (see below) of the element holding the pipe's reading file descriptor; itb(WRITE) The index in bf(d_fd[]) (see below) of the element holding the pipe's writing file descriptor ) manpagesection(PROTECTED DATA) itemization( itb(int d_fd[2]) The array holding the pipe's file descriptors. The bf(READ) element contains the pipe's reading file descriptor, the bf(WRITE) element contains the pipe's writing file descriptor, ) manpagesection(EXAMPLE) verb( #include #include #include #include #include #include using namespace std; using namespace FBB; int main() { Pipe p; // construct a pipe cout << "Read file descriptor: " << p.getReadFd() << endl; cout << "Write file descriptor: " << p.getWriteFd() << endl; int pid = fork(); if (pid == -1) return 1; if (!pid) //child { p.readFrom(STDIN_FILENO); // read what goes into the pipe string s; getline(cin, s); cout << "CHILD: Got `" << s << "'" << endl; getline(cin, s); cout << "CHILD: Got `" << s << "'" << endl; return 0; } p.writtenBy(STDOUT_FILENO); // write to the pipe via cout cout << "first line" << endl; cout << "second line" << endl; waitpid(pid, 0, 0); return 0; } ) manpagefiles() em(bobcat/pipe) - defines the class interface manpageseealso() bf(bobcat)(7), bf(pipe)(2), bf(mkfifo)(3) manpagebugs() Note that when the pipe goes out of scope, no bf(close)(2) operation is performed on the pipe's ends. If the pipe should be closed by the desctructor, derive a class from bf(Pipe)(3bobcat), whose destructor performs the required closing-operation. includefile(include/trailer) bobcat-3.19.01/documentation/man/randbuffer.yo0000644000175000017500000000336212222576536020234 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::RandBuffer)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (random number streambuf) manpagename(FBB::RandBuffer)(std::streambuf generating random numbers) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB:RandBuffer) objects may be used as a bf(std::streambuf) of tt(std::istream) objects to allow the extraction of random numbers from the stream. includefile(include/namespace) manpagesection(INHERITS FROM) std::streambuf manpagesection(CONSTRUCTOR) itemization( itb(Randbuffer(int min, int max, size_t seed = 1)) This bf(Randbuffer()) constructor initializes the random generator. The seed is used to initialze the random number generator.Random values between tt(min) and tt(max) (inclusive) are returned. ) manpagesection(VIRTUAL MEMBERS) itemization( itb(int underflow()) This function is called by tt(std::istream) objects using bf(Randbuffer). It produces the next available random number, separating the random numbers by one blanks space. Random values between tt(min) and tt(max) (inclusive) are returned (see the description of the constructor). ) manpagesection(INHERITED MEMBERS) Since the class uses public derivation from bf(std::streambuf), all members of this class can be used. manpagesection(EXAMPLE) verbinclude(../../randbuffer/driver/driver.cc) manpagefiles() em(bobcat/randbuffer) - defines the class interface manpageseealso() bf(bobcat)(7), bf(irandstream)(3bobcat), bf(rand)(3), bf(srand)(3), bf(std::streambuf) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/milter.yo0000644000175000017500000006430512222576536017416 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Milter)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Milter interface) manpagename(FBB::Milter)(Interface to the sendmail mail filter facilities) manpagesynopsis() bf(#include )nl() Linking option: tt(-lmilter -lbobcat) manpagedescription() bf(Milter) defines an abtract base class interfacing to the sendmail mail filter (milter) facilities. It defines a bf(C++) interface, based on the assumption that a single mail filter program does not implement multiple mail filters. The traditional sendmail bf(C)-based Milter API uses a (tt(SMFICTX)) pointer representing a mail connection, and a pointer to connection-specific `private' data, requiring the Milter constructor to perform quite a few administrative tasks. While acceptable in a bf(C) environment these administratve tasks distract from the main task: the Milter's mail filtering functionality. The bf(FBB::Milter) class hides these administrative tasks from the programmer, who is then able to concentrate on filtering mail. The main benefits of bf(Milter) are therefore itemization( it() Basic administration is performed by the bf(Milter) class it() The class' interface is more bf(C++) like than the raw bf(C) interface offered by the milter API. it() Administration, allocation and communicating of connection specific data is no longer required it() It is not normally necessary to use connection-specific data, like a pointer identifying the connection, anymore when implementing the Milter. it() bf(Milter) uses current-day design patterns enforcing principles of reuable software, thus simplifying the construction of the actual Milter. ) To activate a milter from the tt(sendmail.mc) configuration file, use, e.g., tt(INPUT_MAIL_FILTER(`name', `S=socket')), where tt(name) is the milter's name, and tt(socket) is the name of the socket. See also the tt(setConnection) member below. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ENUMERATIONS) The class defines four enumerations. One enumeration is used to indicate the callback-functions that need to be called, the second one renames the flags that can be passed to sendmail to indicate which actions the milter is allowed to perform. The third one defines status values that may be used to inform sendmail how to further process a message. The fourth one defines return values. The enumerations are: bf(enum CallBack)nl() This enumeration holds the following values: itemization( itb(CONNECT) Indicates that the milter defines (overrides) the connection-functionality. This is the first callback function that can be called by sendmail. itb(HELO) Indicates that the milter defines (overrides) the helo-functionality. This indicates that the tt(helo) function should be called by sendmail, providing the milter with information about the connecting client. itb(SENDER) Indicates that the milter defines (overrides) the sender-functionality. This indicates that the tt(sender) function should be called by sendmail, providing the milter with the sender's envelope information. itb(RECIPIENT) Indicates that the milter defines (overrides) the recipient-functionality. This indicates that the tt(recipient) function should be called by sendmail, providing the milter with the recipient's envelope information. itb(HEADER) Indicates that the milter defines (overrides) the header-functionality. This indicates that the tt(header) function should be called by sendmail for each mail header that is used in the current mail message. itb(EOH) Indicates that the milter defines (overrides) the end-of-header-functionality. This indicates that the tt(eoh) function should be called by sendmail once all header lines have been processed. itb(BODY) Indicates that the milter defines (overrides) the body-functionality. This indicates that the tt(body) function should be called by sendmail, offering the mail-body to the milter. itb(EOM) Indicates that the milter defines (overrides) the end-of-message-functionality. This indicates that the tt(eom) function should be called by sendmail, once all elements of the e-mail message have been processed. itb(ABORT) Indicates that the milter defines (overrides) the abort-functionality. The tt(abort) function may be called by sendmail before tt(eom) is called. It should reclaim all resources used by the message, but not delete any memory allocated by the milter, as this is tt(close)'s job. itb(CLOSE) Indicates that the milter defines (overrides) the close-functionality. The tt(close) function should delete all (connection specific) memory allocated by the milter. It may be called `out-of-order', i.e. even before tt(connect) is called and developers should anticipate this possibility when crafting their tt(close) code. In particular, it is incorrect to assume the private context pointer will be something other than 0 in this callback. itb(UNKNOWN) Currently not used. Reserved for versions exceeding version 2 of the sendmail milter API itb(DATA) Currently not used. Reserved for versions exceeding version 3 of the sendmail milter API itb(ALL_CALLBACKS) Shortcut to indicate all callback facilities. The tt(CallBack) values are bit-flags. The tt(bit_or) operator may be used to combine them, and the tt(bit_not) operator may be used to remove a flag from tt(ALL_CALLBACKS) (e.g., tt(ALL_CALLBACKS && ~ABORT)). ) bf(enum Flags)nl() This enumeration holds the following values: itemization( itb(NO_FLAGS) No flags are defined. itb(ADD_HEADERS) This flag indicates that the milter is allowed to add headers to the current e-mail message. itb(ADD_RECIPIENTS) This flag indicates that the milter is allowed to add recipients to the current e-mail message. itb(CHANGE_BODY) This flag indicates that the milter is allowed to modify the message's body contents. itb(CHANGE_HEADERS) This flag indicates that the milter is allowed to change headers of the current e-mail message. itb(DELETE_RECIPIENTS) This flag indicates that the milter is allowed to remove recipients from the current e-mail message. itb(QUARANTINE) This flag indicates that the milter is allowed to request sendmail to quarantine the current e-mail message. itb(ALL_FLAGS) Shortcut to indicate all callback facilities. The tt(Flags) values are bit-flags. The tt(bit_or) operator may be used to combine them, and the tt(bit_not) operator may be used to remove a flag from tt(ALL_FLAGS) (e.g., tt(ALL_FLAGS && ~QUARANTINE)). ) bf(Status)nl() This enumeration simplifies the extended tt(SMFIS_) values used by the bf(C) API. These values may be used to return tt(sfsistat) values: itemization( itb(ACCEPT) This value is equal to tt(SMFIS_ACCEPT), indicating that Sendmail should accept the message. For a connection-oriented callback (see below at bf(PROTECTED VIRTUAL MEMBER FUNCTIONS)), accept this connection without further filter processing, call tt(close) (see below). For other callbacks: accept this message without further filtering. itb(CONTINUE) This value is equal to tt(SMFIS_CONTINUE), indicating that Sendmail should continue processing. This is the default for all callback functions which are not overridden by the class derived from bf(Milter). itb(DISCARD) This value is equal to tt(SMFIS_DISCARD), indicating that Sendmail should discard the mail message. It should not be returned by a connection-oriented callback. For other callbacks: the message is accepted, but silently discarded. itb(REJECT) This value is equal to tt(SMFIS_REJECT), indicating that Sendmail should reject the mail message. For a connection-oriented callback, reject this connection; call tt(close). For a message-oriented callback (except for tt(eom) or tt(abort, see below)), reject this message. For a recipient-oriented callback, reject the current recipient (but continue processing the current message). itb(TEMPFAIL) This value is equal to tt(SMFIS_TEMPFAIL), indicating that Sendmail should return a `temporary unavailable' message to the sender of the mail message. For a message-oriented callback (except tt(sender), see below), fail for this message. For a connection-oriented callback, fail for this connection and call tt(close). For a recipient-oriented callback, only fail for the current recipient and continue message processing. ) bf(Return)nl() This enumeration simplifies the extended tt(MI_) values used by the bf(C) API. Most return values used by the bf(Milter) class, however, are tt(bool) values. The tt(Return) values are: itemization( itb(FAILURE) This value is equal to tt(MI_FAILURE), indicating that a bf(C)-api function failed to perform its task. itb(SUCCESS) This value is equal to tt(MI_SUCCESS), indicating that a bf(C)-api function succeeded in performing its task. ) manpagesection(CONSTRUCTORS) The default- and copy constructors are available for derived classes. They perform no actions. manpagesection(PUBLIC STATIC MEMBER FUNCTIONS) These functions form the heart of the bf(Milter) base-class. They can be called to initialize, start and stop the Milter. itemization( itb(void initialize(std::string const &name, Milter &milter, callback_set callbacks = CONNECT, flag_set flags = NO_FLAGS)) This function initializes the Milter's administration. It expects the name of the mailfilter as its first argument. Its second argument is a reference to a tt(Milter) object. Since bf(Milter) is an abstract base class the actual object is always an object of a class derived from bf(Milter). Its third argument specifies the callbacks to call for this milter. By default the tt(connect) callback will be called. Note that the tt(close) callback is not called by default. This is ok, since the bf(Milter) object doesn't have to cleanup `private' data, as is normal with the bf(C) API. The last argument defines flags, specifying the Milter's capabilities. itb(std::string const &name()) This function returns the milter's name. itb(bool start()) This member function calls tt(smfi_main), controlling the milter's event loop. It returns tt(true) if the event-loop is successfully terminated. itb(void stop()) This member function terminates the milter's event loop, after finishing all threads. Following this call tt(start) may be called again to continue the milter. ) manpagesection(PROTECTED VIRTUAL MEMBER FUNCTIONS) The remaining functionality of the class tt(Milter) is useful only for Milter-implementations in classes derived from bf(Milter). The following members can be overridden by derived classes. Note that tt(clone) em(must) be overridden. Except for tt(clone), all the members in this sections are em(callback) functions. I.e., the MTA will call them to process parts of the mail message. Recipient-, message-, and connection-oriented callbacks are distinguished. The recipient-oriented callback (tt(recipient), see below) may affect the processing of a single message to a single recipient. Connection-oriented callbacks (tt(connect, helo) and tt(close)) affect the processing of the entire connection (during which multiple messages may be delivered to multiple sets of recipients). The remaining callbacks are message-oriented, affecting the processing of a single message to all its recipients. itemization( itb(virtual sfsistat abort()) This message-oriented member may be called at any time during message processing (i.e. between some message-oriented routine and tt(eom)). tt(abort) reclaim any resources allocated on a per-message basis (which are em(not) the connection specific data, which should be handled by the derived class' destructor), and must be tolerant of being called between any two message-oriented callbacks. tt(abort) is only called if the message is aborted outside the filter's control and the filter has not completed its message-oriented processing. For example, if a filter has already returned tt(ACCEPT, REJECT), or tt(DISCARD) from a message-oriented routine, tt(abort) will not be called even if the message is later aborted outside its control. itb(virtual sfsistat body(unsigned char *text, size_t length)) This message-oriented member is called zero or more times between tt(eoh) and tt(eom). tt(text) points to a sequence of bytes. It is not necessarily a 0-terminated. Moreover, the sequence may contain 0-characters. Since message bodies can be very large, defining tt(body) can significantly impact filter performance. End-of-lines are represented as received from SMTP (normally CR/LF). Later filters will see body changes made by earlier ones, and message bodies may be sent in multiple chunks, with one call to tt(body) per chunk. itb(virtual Milter *clone() const = 0) This pure virtual function must be implemented by derived classes to return a newly allocated copy of the derived object passed to the tt(initialize) static member. It is used by the standard `virtual constructor' design pattern. The destruction of the allocated object is the responsibility of tt(clone)'s caller. itb(virtual sfsistat close()) This connection-oriented member is always called once at the end of each connection. It may be called "out-of-order", i.e. before even the tt(connect) is called. After a connection is established by the MTA to the filter, if the MTA decides this connection's traffic will be discarded (e.g. via an access_db result), no data will be passed to the filter from the MTA until the client closes down. At that time, tt(close) is called. It can therefore be the only callback ever used for a given connection, and developers should anticipate this possibility when crafting their tt(close) code. The member tt(close) is called on close even if the previous mail transaction was aborted. itb(virtual sfsistat connect(char *hostname, _SOCK_ADDR *hostaddr)) This connection-oriented member may be called once, at the start of each SMTP connection. The parameter tt(hostname) is he host name of the message sender, as determined by a reverse lookup on the host address. If the reverse lookup fails, hostname will contain the message sender's IP address enclosed in square brackets (e.g. tt([a.b.c.d])). The parameter tt(hostaddr) is the host address, as determined by a bf(getpeername)(2) call on the SMTP socket. It is 0 if the type is not supported in the current version or if the SMTP connection is made via stdin. itb(virtual sfsistat data()) Not yet supported. Will be available with libmilter versions beyond 3. itb(virtual sfsistat eoh()) This message-oriented member is called once after all headers have been processed. itb(virtual sfsistat eom()) This message-oriented member is called once after all calls to tt(body) for a given message have been completed. Note that only in this function modifications to the message headers, body, and envelope can be made (see the tt(add-, change-) and tt(delete-) members listed below). itb(virtual sfsistat header(char *headerf, char *headerv)) This message-oriented member is called zero or more times between tt(recipient) and tt(eoh), once per message header. The tt(headerf) parameter contains the text of the header, the tt(headerv) parameter contains its value. E.g., if an e-mail message contains the following headers: verb( From: sender Subject:no ) then tt(header) will be called twice with the following values for, respectively tt(headerf) and tt(headerv): verb( First header: "From", " sender " Second header: "Subject", "no" ) Further details about header information is given in RFC 882. itb(virtual sfsistat helo(char *helohost)) This connection-oriented member is called whenever the client sends a HELO/EHLO command. It may therefore be called between zero and three times. The tt(helohost) parameter should be the domain name of the sending host (but is, in practice, anything the sending host wants to send). itb(virtual sfsistat recipient(char **argv)) This recipient-oriented member is called once per recipient, hence one or more times per message, immediately after tt(sender). The parameter tt(argv) is a 0-terminated array of pointers to SMTP command arguments; argv[0] is guaranteed to be the recipient address. Later arguments are the ESMTP arguments. TEMPFAIL may be returned indicate that sendmail should return a temporary failure for this particular recipient; further recipients may still be sent, tt(abort) is not called. REJECT will reject this particular recipient; further recipients may still be sent, tt(abort) is not called. DISCARD will accept (but discard) the message, tt(abort) will be called. ACCEPT will accept recipient, tt(abort) will not be called. More details on ESTMP responses, are described in RFC 1869. itb(virtual sfsistat sender(char **argv)) This message-oriented member is called once at the beginning of each message, before tt(recipient). argv[0] is guaranteed to be the sender's envelope address. Later arguments are the ESMTP arguments. TEMPFAIL may be returned, indicating that sendmail should return a temporary failure for this particular message, tt(abort) is not called. REJECT will reject this message, tt(abort) is not called. DISCARD will accept (but discard) the message, tt(abort) will be called. ACCEPT will accept recipient, tt(abort) will not be called. More details on ESTMP responses, are described in RFC 1869. itb(virtual sfsistat unknown(char *ptr)) Not yet supported. Will be available with libmilter versions beyond 2. ) manpagesection(PROTECTED MEMBER FUNCTIONS) The following members are non-virtual. They can be called by members of classes derived from bf(Milter): itemization( itb(bool addHeader(std::string const &hdrName, std::string const &hdrValue)) This member may only be called from tt(eom), and the flag tt(ADD_HEADERS) must have been specified or it will fail. The tt(hdrName) and tt(hdrValue) must be non-empty strings. Each line of the header must be under 2048 characters and should be under 998 characters. If longer headers are needed, make them multi-line. To make a multi-line header, insert a line feed (tt(\n)) followed by at least one whitespace character such as a space or tab (tt(\t)). The line feed should em(not) be preceded by a carriage return. It is the filter writer's responsibility to ensure that no standards are violated. itb(bool addRecipient(std::string const &rcptName)) This member may only be called from tt(eom), and the flag tt(ADD_RECIPIENTS) must have been specified or it will fail. itb(bool changeHeader(std::string const &hdrName, size_t headerNr, std::string const &hdrValue)) This member may only be called from tt(eom), and the flag tt(CHANGE_HEADERS) must have been specified or it will fail. See tt(addHeader) for the header-requirements. The tt(headerNr) parameter is a 1-based header index value. A tt(headerNr) value of 1 will modify the first occurrence of a header named tt(hdrValue). If tt(headerNr) is greater than the number of times tt(hdrName) appears, a new tt(hdrName)-header will be added. If tt(hdrValue) is empty, the header is deleted. itb(bool deleteRecipient(std::string const &rcptName)) This member may only be called from tt(eom), and the flag tt(DELETE_RECIPIENTS) must have been specified or it will fail. This member removes the named recipient from the current message's envelope. itb(SMFICTX *id() const) This member may be called by the Milter object to obtain a pointer identifying its sendmail-connection. Normally it should not be necessary to call this member. itb(bool insertHeader(size_t hdrIdx, std::string const &hdrName, std::string const &hdrValue)) This member may only be called from tt(eom), and the flag tt(ADD_HEADERS) must have been specified or it will fail. See tt(addHeader) for the header-requirements. The tt(headerNr) parameter is a header index value. A tt(headerNr) value of 0 will insert this header as the first of the tt(hdrName) headers. If tt(headerNr) is greater than the number of times tt(hdrName) appears, a new tt(hdrName)-header will be added. itb(bool openSocket(bool removeIfTrue = true)) This member should be called before tt(start) is called. This member attempts to create the socket specified by tt(setConnection) (see below). This allows the calling application to ensure that the socket can be created, possibly changing its protection (access rights) before the milter starts its work. If this member is not called, it will be called implicitly when tt(run) is started. It returns tt(true) if the socket could be created. itb(bool quarantine(std::string const &reason)) This member may only be called from tt(eom) and causes the MTA to quarantines the message using the given reason. itb(bool replaceBody(std::string const &body)) This member may only be called from tt(eom), and the flag tt(CHANGE_BODY) must have been specified or it will fail. It may be called multiple times in which case the various body contents are concatenated in the final message. Newlines should be coded as CRLF. itb(bool setBacklog(size_t backlog = 5)) This member should be called before tt(start) is called. Sets the incoming socket backlog used by bf(listen)(2). If tt(setBacklog) is not called, the operating system default is used. The function returns tt(false) if the backlog could not be set as requested. It is the responsibility of the programmer not to call this function with a 0 argument. itb(bool setConnection(std::string const &name)) This member should be called before tt(start) is called. Sets the socket through which the filter communicates with sendmail. The socket may be specified using one of the following variants:nl() tt({unix|local}:/path/to/file) - A named pipe;nl() tt(net:port@{hostname|ip-address}) - An IPV4 socket;nl() tt(inet6:port@{hostname|ip-address}) - An IPV6 socket.nl() If possible, filters should not run as root when communicating over unix/local domain sockets. Unix/local sockets should have their permissions set to 0600 (read/write permission only for the socket's owner) or 0660 (read/write permission for the socket's owner and group) which is useful if the sendmail RunAsUser option is used. The permissions for a unix/local domain socket are determined as usual by umask, which should be set to 007 or 077. Possible failure of this function cannot be determined from its return value. Rather, tt(run) will fail. itb(setReply(std::string const &rcode, std::string const &xcode = "", std::string const &msg = "")) This member sets the default SMTP error reply code. It may be called from any callback member, except tt(connect). The parameter tt(rcode) should be a he three-digit (RFC 821/2821) SMTP reply code and it must be a valid 4XX or 5XX reply code. The parameter tt(xcode), when specified, must be a extended (RFC 1893/2034) reply code. The parameter tt(msg) may be an additional textual message. The bf(Milter) class has no member comparable to the libmilter API function tt(smfi_setmlreply). the bf(Milter) class. itb(void setTimeout(size_t seconds = 7210)) This member should be called before tt(start) is called. Sets the number of seconds libmilter will wait for an MTA connection before timing out a socket. If tt(setTimeout) is not called, a default timeout of 7210 seconds is used. It is the responsibility of the programmer not to call this function with an argument equal to 0. itb(char const *symval(std::string const &name) const) This member returns the value of a specific sendmail macro. The tt(name) parameter should be set to he name of a sendmail macro . Single letter macros can optionally be enclosed in braces (tt({) and tt(})), longer macro names must be enclosed in braces, just as in a sendmail.cf file.0 is returned if the macro is not defined. By default, the following macros are valid in the given contexts:nl() for tt(connect): tt(daemon_name, if_name, if_addr, j, _);nl() for tt(helo): tt(tls_version, cipher, cipher_bits, cert_subject, cert_issuer);nl() for tt(sender): tt(i, auth_type, auth_authen, auth_ssf, auth_author, mail_mailer, mail_host, mail_addr);nl() for tt(recipient): tt(rcpt_mailer, rcpt_host, rcpt_addr).nl() All macros stay in effect from the point they are received until the end of the connection for the first two sets, the end of the message for the third (tt(sender)), and just for each recipient for the final set (tt(recipient)).nl() The following macros may be specified in the sendmail.mc configuration file:nl() tt(define(`confMILTER_MACROS_CONNECT', `m1', ...)), tt(define(`confMILTER_MACROS_HELO', ...)), tt(define(`confMILTER_MACROS_ENVFROM', ...)), tt(define(`confMILTER_MACROS_ENVRCPT', ...)), where tt(`m1', ...) represents a comma separated list of returnable macros. Single letter macros can optionally be enclosed in braces (tt({) and tt(})), longer macro names must be enclosed in braces. itb(bool wait()) This member may only be called from tt(eom) and tells the MTA that the filter is still working on a message, causing the MTA to re-start its timeouts. ) manpagesection(EXAMPLE) To do manpagefiles() em(bobcat/milter) - defines the class interface manpageseealso() bf(bobcat)(7), bf(getpeername)(2), bf(listen)(2), nl() tt(http://www.milter.org) (e.g., tt(http://www.milter.org/developers/api))nl() tt(http://sendmail.org/m4/readme.html)nl() tt(http://rfc.net/rfc821.html)nl() tt(http://rfc.net/rfc822.html)nl() tt(http://rfc.net/rfc1869.html)nl() tt(http://rfc.net/rfc1893.html)nl() tt(http://rfc.net/rfc2034.html)nl() tt(http://rfc.net/rfc2821.html)nl() tt(/usr/include/libmilter/mfapi.h) manpagebugs() tt(-lmilter) must be specified before tt(-lbobcat). includefile(include/trailer) bobcat-3.19.01/documentation/man/sharedpos.yo0000644000175000017500000001315312242116103020063 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Sharedpos)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Shared Memory Offsets) manpagename(FBB::Sharedpos)(Shared Memory offset controller) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() The class bf(SharedPos) is a support class for Bobcat's shared memory handling classes. It controls the shared memory read/write ofset and ensures that shared memory operations never exceed the shared memory's maximum offset. The class bf(SharedPos) has several public members, but they are primarily useful for other tt(Shared*) classes offered by Bobcat. There is probably little use for a stand-alone bf(SharedPos) object. In the descriptions of the class's member functions tt(offset) refers to the read/write offset within the available shared memory. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(TYPEDEFS AND ENUMS) manpagesection(CONSTRUCTORS) Default, copy and move constructors are available. The default constructor does not yet monitor the offsets for a shared memory segment. The member tt(reset) is used to start monitoring offsets. manpagesection(OVERLOADED OPERATORS) itemization( itb(void operator++()) The offset is incremented. If this member is called when the offset is equal to the shared memory's maximum offset an tt(FBB::Exception) is thrown. itb(void operator+=(size_t len)) The offset is incremented by tt(len). If tt(offset + len) exceeds the shared memory's maximum offset then the offset is set to the maximum offset and an tt(FBB::Exception) is thrown. itb(std::ostream &operator<<(std::ostream &out, SharedPos const &pos)) Inserts information about the bf(FBB::SharedPos) object into tt(out). ) The copy and move assignment operators are available. manpagesection(MEMBER FUNCTIONS) itemization( itb(bool atMaxOffset() const) Returns tt(true) if offset equals the maximum offset that can be used for the current shared memory segment.nl() The behavior of this member is undefined until tt(setup) has been called. itb(size_t blockIdx() const) The index of the shared segment data block in which offset is located is returned. itb(size_t blockOffset() const) The index within the shared segment data block matching offset is returned. itb(bool eof() const) Returns tt(true) if offset exceeds the maximum offset of any character ever written to the shared memory pointed at by tt(sharedData). If tt(eof) returns tt(true) information may still be em(written) to the shared memory: writting is possible until the maximum shared memory segment offset has been reached.nl() The behavior of this member is undefined until tt(setup) has been called. itb(std::streamsize eos() const) The offset just beyond the maximum offset for the current shared segment data block is returned.nl() The behavior of this member is undefined until tt(setup) has been called. itb(std::streamsize maxOffset() const) The maximum possible offset that can be used for the currently monitored shared memory segment is returned. Zero is returned until tt(setup) has been called. itb(std::streamsize offset() const) The offset within the currently monitored shared memory segment is returned. Zero is returned until tt(setup) has been called. itb(void setup(SharedSegment *sharedData)) The tt(SharedPos) object is reset to monitor the offset of a new tt(FBB::SharedSegment) object. The tt(SharedSegment *) must point to a tt(SharedSegment) segment (cf. bf(sharedsegment)(3bobcat)) that must exist until the end of the bf(FBB::SharedPos) object's lifetime or until the next tt(reset) call. Immediately after calling tt(reset) offset has the value 0. itb(std::streamsize showmanyc() const) The number of characters that can be read from the current shared segment data block is returned. This member interrogates the number of readable characters in the shared memory segment. This number may change while this member is being executed. In order to receive a stable return value, calling functions should have obtained a lock on the shared memory segment before calling this member. See also the bf(sharedsegment)(3bobcat) man-page.nl() The behavior of this member is undefined until tt(setup) has been called. itb(std::ios::pos_type seek(std::ios::off_type offset, std::ios::seekdir way = std::ios::beg)) The monitored offset is changed to this member's tt(offset) argument, relative to tt(way). Seeking beyond tt(eof) is OK; -1 is returned when seeking beyond tt(maxOffset) or seeking before the shared segment's offset 0. ) manpagesection(EXAMPLE) See the bf(sharedstream)(3bobcat) man page. manpagefiles() em(bobcat/sharedpos) - defines the class interface manpageseealso() bf(bobcat)(7), bf(isharedstream)(3bobcat), bf(osharedstream)(3bobcat), bf(sharedblock)(3bobcat), bf(sharedmemory)(3bobcat), bf(sharedmutex)(3bobcat), bf(sharedsegment)(3bobcat), bf(sharedstream)(3bobcat), bf(sharedstreambuf)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/hmacbuf.yo0000644000175000017500000001117512222576536017524 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Hmacbuf)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Compute HMAC Message Digests) manpagename(FBB::Hmacbuf) (Computes HMAC Message Digests from information inserted into a std::ostream) manpagesynopsis() bf(#include )nl() Linking option: tt( -lbobcat) manpagedescription() bf(FBB::Hmacbuf) objects are bf(std::streambuf) objects that can be used to initialize tt(std::ostream) objects with. All information inserted into such a tt(std::ostream) is used to compute a message HMAC from. All the message digest algorithms defined by the OpenSSL library that can be selected by name may be used in combination with tt(HMacBuf) objects. The following message hmac algorithms are currently supported: mull, md2, md5, sha, sha1, sha224, sha256, sha384, sha512, dss, dss1, ecdsa, mdc2, ripemd160. These very names are the ones to use to select the particular digest algorithm for the class's constructor, below. It is quite possible that future releases of the openssl library will support additional message digest algorithms. The header file tt(openssl/evp.h) lists all available hmac algorithms (in that file look for tt(EVP_MD *EVP_): a message digest algorithm immediately follows the 2nd underscore. E.g., tt(const EVP_MD *EVP_md4(void)) which refers to the md4 message digest algorithm). includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(CONSTRUCTORS) itemization( itb(Hmacbuf(std::string const &key, char const *type, size_t bufsize = 1024)) This constructor initializes the streambuf, setting it up for the message digest algorithm specified with tt(type). The message hmac algorithms specified in the bf(DESCRIPTION) section may be used here. E.g., to use the sha256 algorithm specify tt("sha256"). The constructor's first argument defines the key to be used when computing the HMAC message digest. The tt(bufsize) argument specifies the internal buffer used by tt(Hmacbuf) to store incoming characters temporarily. The provided default argument should be OK in all normal cases. ) There is no copy constructor. manpagesection(OVERLOADED OPERATOR) itemization( itb(std::ostream &operator<<(std::ostream &out, HMacBuf const &hmacbuf)) The insertion operator is a free function defined in the namespace tt(FBB). It inserts a hash value as a series of hexadecimally displayed values into the provided tt(ostream). See the example below for an illustration. ) The overloaded assignment operator is not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::Hmacbuf) inherits from this class. Some of the bf(std::streambuf)'s member are overridden or are hidden by tt(Hmacbuf). In normal situations these inherited members will not be used by programs using tt(HMacBuf) objects. itemization( itb(void close()) This member finishes the computation of the message digest computation. It is needed as the tt(HMacBuf) object has no external means for deciding whether all information to compute the digest for has yet been received or not. The general approach to follow when computing a message hmac is therefore: verb( create a HMacBuf object use it to create a std::ostream object insert information into the ostream object call the HMacBuf object's close() member obtain/process the hash value from the HMacBuf object. ) itb(std::string const &hash() const) This member returns the hash value computed by the tt(HMacBuf) object. Its value is only defined after having called tt(close()). The hash value is returned in a tt(std::string) object. This string's tt(length()) member contains the number of characters used by the hash value, and its tt(data()) member refers to the hash value's characters. Note that a hash value's character value may be 0 (not to be confused with tt('0')). itb(void open()) This member reinitializes the message hmac computation. One a message hmac has been computed for, say a stream tt(streamA) this member can be called after which the hmac for a stream tt(streamB) can be computed using the same tt(HMacBuf) object. ) manpagesection(EXAMPLE) verbinclude(../../hmacbuf/driver/driver.cc) manpagefiles() em(bobcat/hmacbuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(digestbuf)(3bobcat), bf(std::streambuf) manpagebugs() None reported includefile(include/trailer) bobcat-3.19.01/documentation/man/process.yo0000644000175000017500000010063112257542303017562 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Process)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Running Child Processes) manpagename(FBB::Process)(Runs external programs) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() The bf(FBB::Process) class offers an extensive interface to calling external programs and/or scripts from a bf(C++) program (so-called em(child-processes)). The class offers an easy to use, stream-based interface to the standard input, standard output and standard error streams of child processes. Objects of the tt(class Process) use standard process-executing functions, like members of the bf(execl)(1) family or bf(sh)(1) to execute child processes. Thus, child processes can be executable programs or em(shell-scripts). The standard input, output and error streams of child processes may be accessed through their tt(Process) parent objects. Input expected by child processes may be inserted by tt(Process) objects, and output generated by child processes may be extracted from tt(Process) objects. When using (output) redirection with the tt(USE_SHELL) path specification (see below for the path and IOMode specifications), the tt(IGNORE_COUT IOMode) (and possibly tt(IGNORE_CERR)) should normally be specified (see also this man-page's bf(PIPING) section). tt(Process) objects may repeatedly be used to execute the same or different child processes. Before the next child process is started, the tt(Process) object first terminates its currently active child process. Alternatively, a currently active child process is automatically ended if the tt(Process) object goes out of scope, if its tt(stop) or tt(eoi) (end-of-information) member is called, or if the tt(eoi) manipulator is inserted into the tt(Process) object. Programs to be called as child processes may be specified at tt(Process's) constructor-time or through tt(Process's setCommand) member. tt(Process) constructors (or tt(Process set)-members) never start child processes. Child processes are started through tt(start) members or the assignment operator. Child processes may receive information at their standard input streams through information inserted into tt(Process) objects. In these cases the tt(Process) objects must inform their child processes that they have received all input. For this the tt(close) or tt(eoi) member or the tt(eoi) manipulator can be used. After calling the tt(close) member, the tt(waitForChild) member should be called as well. This is not necessary if either the tt(eoi) member or the tt(eoi) manipulator is used. If tt(waitForChild) is not called (but information sent to the child which could not be fully processed by the child process in case the child process terminated as a result of the tt(Process) object going out of scope), then the operating system issues a tt(Broken pipe) message, indicating that information in a pipe was lost. Arguments passed to child processes may be surrounded by double or single quotes. Arguments surrounded by double quotes have their double quotes removed, while interpreting any escape-sequences that may have been used within. Arguments surrounded by single quotes have their single quotes removed, while accepting their contents as-is. In addition unquoted escape-sequences may be specified: those escape sequences are evaluated and replaced by their intended characters (e.g., tt(\100) is converted to tt(@)). A full command specification may be surrounded by backtics (tt(`)-characters). These backtick characters are removed by the tt(Process) object when the command is started. Child processes may be allowed a limited amount of time (in seconds) to complete. By default no time limit is imposed upon child processes. By default the standard input, output and error streams of child processes are accessed through their tt(Process) parent processes: information inserted into the tt(Process) object is forwarded to the child process's standard input stream, information sent by the child process to its standard output stream can be extracted from its parent tt(Process) object, and information sent by the child process to its standard error stream may be obtained through tt(Process's childErrStream) member. If the parent and child processes have agreed on some communication process, then information may alternatingly be sent to and received from the child process through the tt(Process's ostream) and tt(istream) facilities. Alternatively, unspecified amounts of information written by child processes may be processed by separate threads (cf. this manual page's bf(EXAMPLES) section). includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::Fork)(3bobcat) (private), nl() bf(FBB:IOStream)(3bobcat) bf(FBB:ProcessEnums) The tt(struct ProcessEnums) defines enumerations and support functions which are used by several classes. Its enumerations are documented below; there is no separate bf(ProcessEnums) man-page. manpagesection(ENUMERATIONS) bf(enum ProcessType):nl() The bf(enum ProcessType) defines how a child process is started or located. Its values are specified at constructor-time or through the tt(setProcessType) member. This enumeration defines the following symbolic constants: itemization( itb(NO_PATH) The program specified as child process is started as specified, without searching the elements of the tt(PATH) environment variable. itb(USE_PATH) The elements of the tt(PATH) environment variable are used when locating the program specified as child process. itb(USE_SHELL) The program specified as child process is called using tt(/bin/sh -c). When (output) redirection is used with the specified command the tt(IGNORE_COUT IOMode) (and possibly also the tt(IGNORE_CERR IOMode)) should be specified. ) bf(enum IOMode):nl() Values of the tt(enum IOMode) are used to define which of the child process's standard streams can be accessed through the tt(Process) object. Its symbolic constants may be combined using the tt(bit_or) operator. By default tt(CIN | COUT | CERR) is used (see below). The following symbolic constants are available: itemization( itb(ALL) Shortcut for bf(CIN | COUT | CERR). itb(CIN) Information inserted into the tt(Process) object is forwarded to its child process. If this is not required then tt(CIN) should not be specified. itb(CERR) Information written by the child process to its standard error stream is accessible through tt(Process's childErrStream) member. If this is not required then tt(CERR) should not be specified. itb(COUT) Information written by the child process to its standard output stream may be directly be extracted from the tt(Process) object, or from its tt(childOutStream) member. If this is not required then tt(CERR) should not be specified. itb(DIRECT) When starting a child process (see below at the member tt(start)) the current process (i.e., the program defining the tt(Process) object) is replaced by the child process, inheriting the current process's standard input and output streams. If this mode is specified in combination with any other tt(IOMode) (except for tt(STD), see below) an tt(std::invalid_argument) exception is thrown. itb(IGNORE_CERR) Information written by the child process to its standard error stream is sent to tt(/dev/null). An tt(std::invalid_argument) exception is thrown if this mode is specified in combination with bf(DIRECT, CERR) and/or bf(MERGE_COUT_CERR). itb(IGNORE_COUT) Information written by the child process to its standard output stream is sent to tt(/dev/null). An tt(std::invalid_argument) exception is thrown if this mode is specified in combination with bf(COUT, DIRECT) and/or bf(MERGE_COUT_CERR). itb(IGNORE_COUT_CERR) Shortcut for tt(IGNORE_CERR | IGNORE_COUT). itb(MERGE_COUT_CERR) Information extracted from the tt(Process) object is written by the child process to its standard output and standard error streams. An tt(std::invalid_argument) exception is thrown if this mode is specified in combination with bf(COUT, CERR, DIRECT, IGNORE_COUT) or tt(IGNORE_CERR). itb(NONE) The tt(Process) object does not extract information from or insert information into the standard streams of its child process. The child process reads the same standard input stream and writes the same standard output streams as its parent tt(Process) object. When this mode is specified in combination with other tt(IOMode) values it is silently ignored. ) bf(enum ChildOutput):nl() The tt(ChildOutput) enumeration defines values returned by the tt(available) member (see below) indicating to which standard stream the child process has written information. This enumeration defines the following values: itemization( itb(NOTHING_AVAILABLE) The child process did not (yet) write any information to its standard streams; itb(CHILD_COUT) The child process wrote information to its standard output stream which is waiting for extraction. itb(CHILD_CERR) The child process wrote information to its standard error stream which is waiting for extraction. ) The latter two values may be combined using the tt(bit_or) operator. The tt(bit_and) operator,returning a tt(bool) value can be used to test whether information on a specific output stream is available. manpagesection(PROCESS PARAMETERS) Four process parameters may be specified: the sizes of the stream buffers which are used when communicating with child processes; to specify which of the standard streams of child processes can be accessed from the tt(Process) object combinations of tt(IOMode) values are used; to specify how child programs are found a tt(ProcessType) value is used; to specify the maximum time (in seconds) the child program is allowed to run a tt(size_t) values is used. By default, the stream buffers hold 200 bytes; all the child's standard streams (standard input, output and error) are accessible from the tt(Parent) process; the tt(PATH) environment variable is em(not) used to locate the child program; and the child processes will be allowed an unlimited amount of time to run. After constructing a tt(Process) object all default parameters may be modified. These parameters may either be altered for a single process or a tt(Process) object's general defaults may be modified. The tt(set*) members (see below) may be used to change the default process parameters. When parameters are specified otherwise, they will only be active for the next process. manpagesection(CONSTRUCTORS) The command provided to the following constructors may be the (initial part of the) specification of an external program to run. When the program is eventually started it may start and end with a em(back-tick) (tt(`)). The back-ticks will be removed just before the specified program is executed. Child processes are em(not) started automatically following tt(Process) object constructions. A tt(start) member or the assignment operator (see below) is used to start the specified child process. The tt(mode) parameter that is defined for the second through fourth constructor is defined as a tt(size_t) for backward compatibility reasons. Internally, this argument is immediately converted to a tt(Process::IOMode) value, silently ignoring values which do not represent valid tt(IOMode) values. Multiple tt(IOMode) values may be combined using the bit-or operator. After constructing a tt(Process) object its parameters can be changed using tt(set)-member functions, function call operators or tt(start) members. itemization( itb(Process(std::string const &cmd = "")) This constructor is used to specify the (initial part of a) command to execute from a tt(Process) object. Default values are used for the process parameters (see section bf(PROCESS PARAMETERS)). itb(Process(size_t mode, std::string const &cmd = "")) This constructor requires the specification of the object's bf(IOMode), and it can be used to specify the (initial part of a) command to execute from a tt(Process) object. Default values are used for the remaining process parameters (see section bf(PROCESS PARAMETERS)). itb(Process(size_t mode, ProcessType type, std::string const &cmd = "")) This constructor requires the specification of the object's bf(IOMode) and tt(ProcessType), and it can be used to specify the (initial part of a) command to execute from a tt(Process) object. Default values are used for the remaining process parameters (see section bf(PROCESS PARAMETERS)). itb(Process(size_t mode, ProcessType type, size_t timeLimit, std::string const &cmd = "")) This constructor requires the specification of the object's bf(IOMode), tt(ProcessType), and child process time limit. The (initial part of a) command to execute from a tt(Process) object may optionally be specified. The default process parameter is used for the sizes of the internally used stream buffers (see section bf(PROCESS PARAMETERS)). itb(Process(IOMode mode, ProcessType type, size_t timeLimit, size_t bufferSize, std::string const &cmd = "")) This constructor requires the specification of the object's bf(IOMode), tt(ProcessType), child process time limit, and size of the internally used stream buffers. The (initial part of a) command to execute from a tt(Process) object may optionally be specified. Note that this constructor's tt(mode) parameter does not accept a tt(size_t) argument. ) The class bf(Process) does not offer copy or move constructors. manpagesection(OVERLOADED OPERATORS) itemization( itb(Process &operator<<(Type value)) This operator inserts tt(value) into the child's standard input stream. I.e., the child process reads tt(value) from its standard input. A value of any type that can be inserted into an tt(ostream) can be inserted into a tt(Process) object. Nothing happens if the member is used when the child process has terminated. The behavior of this operator is undefined unless tt(IOMode CIN) was specified. itb(Process &operator>>(Type value)) This operator extracts tt(value) from the child's standard output stream and optionally (if tt(IOMode MERGE_COUT_CERR) was specified) from the child's error stream. I.e., tt(value) may be extracted from tt(Process) objects. A value of any type that can be extracted from an tt(istream) can be extracted from a tt(Process) object. Nothing happens if the member is used when the child process has terminated. The behavior of this operator is undefined unless tt(IOMode COUT) or tt(MERGE_COUT_CERR) was specified. itb(Process &operator+=(std::string const &)) This operator adds the provided tt(std::string) object to the currenly defined command specification of a tt(Process) object. The member tt(operator+=) does not add a separating blank space between the currently stored command specification and the text to append. It merely adds its right-hand side string to the command stored so far. It does not affect a currently running child process. itb(int operator=(std::string const &cmd)) The tt(operator=) member defines tt(cmd) as the stored command in a tt(Process) object. Before starting the child process a possibly active child process is first stopped by calling tt(stop). It returns tt(stop)'s return value. itb(Process &operator()(IOMode mode)) This operator changes the the tt(Process) object's tt(IOMode) parameter. A reference to the tt(Process) object is returned, allowing constructions like verb( process(Process::COUT) = "/bin/cat"; ) to start a new child process with the specified tt(IOMode). itb(Process &operator()(IOMode mode, ProcessType type)) This operator changes the tt(Process) object's tt(IOMode) and tt(ProcessType) process parameters. itb(Process &operator()(size_t mode, ProcessType type, size_t timeLimit)) This operator changes the tt(Process) object's mentioned process parameters, silently converting the tt(size_t mode) to an tt(IOMode) value. The currently specified default size of the stream buffers is kept as-is. itb(Process &operator()(IOMode mode, ProcessType type, size_t timeLimit, size_t bufferSize)) This operator changes all of the tt(Process) object's process parameters. itb(Process &operator|(Process &lhs, Process &rhs)) This operator implements process em(piping): information sent b tt(lhs) to its standard output becomes the tt(rhs)'s standard input. The operator returns tt(rhs). This operator mimics the piping-operator supported by most command-shell programs and should not be confused with the binary-or operator. The operator starts the tt(lhs)'s child process, but the tt(rhs)'s child process (and thus pipe processing) must explicitly be started. Since tt(operator|) is left-associative and tt(rhs) is returned piping can be em(chained), allowing constructions like tt(p1 | p2 | p3), where tt(p1, p2) and tt(p3) are tt(Process) objects. The following idiom can be used to start the execution of a chain of processes: tt((p1 | p2 | p3).start()). Alternatively, the following two-step procedure can be used: verb( p1 | p2 | p3; p3.start(); ) If tt(p1) specifies tt(Process::CIN) then this tt(IOMode) is forwared to the final process of the chain of processes. It is not necessary to specify tt(Process::CIN) for tt(p3). In fact, most tt(IOMode) flags of processes passed to tt(operator|) are ignored or modified. Acceptable tt(IOModes) are tt(Process::IGNORE_CERR) and tt(Process::CERR) (accepted for all processes), tt(Process::CIN) (accepted for the first process of the chain), and tt(Process::COUT) (for the last process of the chain). After connecting a series of processes using tt(operator|) all input and output (except for the standard error streams) is handled through the last process: if tt(Process::CIN) is specified for the first process then this mode is transferred to the last process, so information inserted into the last process enters the pipe through the first process's standard input. The next example illustrates how input can be inserted into the first process from a main process and sent to the standard output stream by the final process: verb( using namespace std; using namespace FBB; Process p1(Process::CIN, "/bin/cat"); Process p2("/bin/cat"); Process p3(Process::STD, "/bin/cat"); p1 | p2 | p3; p3.start(); p3 << cin.rdbuf() << eoi; ) Note that when specifying multiple commands using the piping operator (tt('|')), traditionally tt(USE_SHELL) had to be specified, as the traditional piping operator is a shell-feature. tt(Process's operator|) handles I/O piping itself, and thus avoids the additional shell process. ) The default overloaded copy and move assignment operators are not available. manpagesection(MEMBERS) itemization( itb(bool active()) This member returns tt(true) if the child process is currently running and tt(false) if not. itb(size_t available()) This member returns immediately. Its return value indicates whether any information can be obtained from the child process as value(s) from the tt(enum ChildOutput). tt(NOTHING_AVAILABLE) is returned if no information is ready for extraction. tt(CHILD_COUT) is returned if information from the child process's standard output stream is available; tt(CHILD_CERR) is returned if information from the child process's standard error stream is available; tt(CHILD_COUT | CHILD_CERR) is returned if information from both the standard output and standard error streams is available. The tt(bit_and) operator, returning a tt(bool) value, can be used to determine which stream has any pending information. E.g., verb( if (process.available() & Process::CHILD_COUT) cout << "Process has child standard output available"; ) itb(size_t bufSize() const) This member returns the default size of the stream buffers that are used for communication with child processes. If called while a child process is actually running, then the value returned by this member may differ from the value that was actually used when starting the child process, as the default value may be altered by a function call operator just before starting the child process. itb(std::istream &cerr()) This member should be avoided. Use tt(childErrStream) instead.nl() itb(std::istream &childErrStream()) If tt(Process::CERR) was specified then this member interfaces to the child's standard error stream. By extracting the information from tt(childErrStream) the parent process retrieves the information sent by its child process to its standard error stream. itb(std::istream &childOutStream()) If tt(Process::COUT) or tt(Process::MERGE_COUT_CERR) was specified then this member interfaces to the child's standard output stream. By extracting the information from tt(childOutStream) the parent process retrieves the information sent by its child process to its standard output stream. Alternatively, this information may directly be extracted from the tt(Process) object itself, but this member does not require the use of a tt(static_cast) to disambiguate the intended stream buffer in statements like verb( cout << process.childOutStream().rdbbuf() ) itb(void close()) This member closes the child's input stream. In situations where the child continuously reads information from its standard input stream this member can be used to inform the child process that input has terminated. This member should only be used when tt(IOMode CIN) was specified for the currently running child process; otherwise its behavior is undefined. Alternatively, the tt(eoi) member or manipulator may be used. itb(void eoi()) This member closes the child's input stream, and then calls tt(waitForChild) to wait for the child process to end. In situations where the child continuously reads information from its standard input stream this member can be used to inform the child process that input has terminated. This member should only be used when tt(IOMode CIN) was specified for the currently running child process; otherwise its behavior is undefined. Alternatively, the tt(close) member or tt(eoi) manipulator may be used. itb(std::istream &errStream()) This member may be used to extract information written by the child process to its standard error stream. This member should only be used when tt(IOMode CERR) was specified for the currently running child process; otherwise its behavior is undefined.nl() itb(IOMode ioMode() const) This member returns the default tt(IOMode). If called while a child process is actually running, then the value returned by this member may differ from the value that was actually used when starting the child process, as the default value may be altered by a function call operator just before starting the child process. itb(ProcessType processType() const) This member returns the default tt(ProcessType) of child proceses. If called while a child process is actually running, then the value returned by this member may differ from the value that was actually used when starting the child process, as the default value may be altered by a function call operator just before starting the child process. itb(size_t timeLimit() const) This member returns the default time limit (in seconds) of child processes. A return value of zero indicates that no time limit is enforced. If called while a child process is actually running, then the value returned by this member may differ from the value that was actually used when starting the child process, as the default value may be altered by a function call operator just before starting the child process. itb(void setBufSize(size_t bufSize)) This member changes the default stream buffer size that is used for communication with child processes. A zero byte buffer size is silently changed into one. The new default value will be used when starting the next child process. itb(void setCommand(std::string const &cmd)) The tt(setCommand) member (re)defines the (initial part of a) child process command specification. This member does not actually start the child process, and tt(operator+=) may be used to append additional text to the command specification. Also, this member may be used when a child process is currently active: its use does not affect a currently running child process. itb(void setIOMode(iomode mode)) This member changes the default tt(IOMode). The new default value will be used when starting the next child process. itb(void setProcessType(ProcessType type)) This member changes the default tt(ProcessType). The new default value will be used when starting the next child process. itb(void setTimeLimit(size_t timeLimit)) This member changes the default execution time limit (in seconds). No time limit will be imposed upon child processes if tt(timeLimit 0) is specified. The new default value will be used when starting the next child process. itb(void start()) The currently specified command is started using the tt(Process) object's process parameters. Having specified a command to start, the first white-space delimited element of the specified command is used as the name of the program to start. If the program should be called through bf(sh)(1), the tt(USE_SHELL ProcessType) or a tt(system) member should be used. If a child process does not terminate by itself, then it is terminated when it has run for its alloted time; when the tt(Process) object's tt(start) or tt(stop) members are called; when the object's assignment operator is used; or when the object goes out of scope. itb(void start(IOMode mode)) The currently specified command is started using the specified tt(IOMode), but otherwise using the currently configured tt(Process) object's process parameters. The specified tt(IOMode) is only used for the child process that is started by this member. itb(void start(IOMode mode, ProcessType type)) The currently specified command is started using the specified tt(IOMode) and tt(ProcessType), but otherwise using the currently configured tt(Process) object's process parameters. The specified process parameter values are only used for the child process that is started by this member. itb(void start(size_t mode, Program program, size_t timeLimit)) The currently specified command is started using the specified tt(IOMode), tt(ProcessType), and time limit (silently converting the tt(size_t mode) to an tt(IOMode) value), and using the currently configured tt(Process) object's stream buffer size parameter. The specified process parameter values are only used for the child process that is started by this member. itb(void start(IOMode mode, Program program, size_t timeLimit, size_t bufferSize)) The currently specified command is started using the specified process parameters. The specified parameter values are only used for the child process that is started by this member. itb(void showMode(char const *lab) const) This member displays the label tt(lab), followed by the current process ID, followed by the child process's process ID, followed by a textual representation of the currently active tt(IOMode). itb(std::string const &str() const) This member returns the contents of the current child process command specification. It shows the command as it will be (or has been) executed by tt(start), tt(system) or the assignment operator. itb(void system()) This member executes the currently stored command as a command to bf(sh)(1). When using tt(system) redirections can be included in the command itself (this renders the redirected streams implied by the current bf(IOMode)) useless. The currently set process parameters are used when bf(sh)(1) is executed. itb(void system(IOMode mode)) This member executes the currently stored command as a command to bf(sh)(1) (cf. tt(system) above) using the specified tt(IOMode) rather than the current default tt(IOMode) setting. itb(void system(IOMode mode, size_t timeLimit)) This member executes the currently stored command as a command to bf(sh)(1) (cf. tt(system) above) using the specified tt(IOMode) and time limit. itb(void system(IOMode mode, size_t timeLimit, size_t bufSize)) This member executes the currently stored command as a command to bf(sh)(1) (cf. tt(system) above) using the specified tt(IOMode), time limit, and stream buffer size values. itb(int stop()) This member terminates a currently active child process. The child process is twice sent a tt(SIG_TERM) signal, followed by a tt(SIG_KILL) signal. This member returns the exit-value of the child process that was stopped. Its operation and return value are undefined if called without a running child process. Following tt(stop) a new command may be called using tt(start, system) or the assignment operator (see earlier). Those members first calls tt(stop). When the intention is to start another child process, then there's no need to call tt(stop) explicitly. Also, tt(stop) is called when the tt(Process) object goes out of scope. itb(int waitForChild()) This member is inherited from the class tt(FBB::Fork). It waits for a child process to end. It is called to prevent premature termination of a child process before calling tt(stop). It is not always necessary to call tt(waitForChild). E.g., when a process writes to its standard output stream and all output has been read then the child process can be stopped without calling tt(waitForChild). ) manpagesection(MANIPULATOR) itemization( itb(FBB::eoi) This manipulator may be inserted into a tt(Process) object for which tt(IOMode CIN) was specified. It closes the child's input stream, and then calls tt(waitForChild) to wait for the child process to end. In situations where the child continuously reads information from its standard input stream this member can be used to inform the child process that input has terminated. Alternatively, tt(Process) object's tt(close) or tt(eoi) members may be used. ) manpagesection(EXAMPLES) The first example shows how a program only producing output can be called. Its child process simply is tt(/bin/ls): verbinsert(CODE)(../../process/driver/ls.cc) The next example shows how a child program can be given a limited amount of execution time: lines entered at the keyboard are echoed to the standard output stream for at most 5 seconds: verbinsert(CODE)(../../process/driver/limit.cc) The final example shows how multi threading can be used to access the child program's standard output and standard error streams through the tt(Process) object: verbinsert(CODE)(../../process/driver/all.cc) Additional examples are found in the distribution's tt(bobcat/process/driver) directory. manpagefiles() em(bobcat/process) - defines the class interface manpageseealso() bf(bobcat)(7), bf(execle)(3), bf(fork)(3bobcat), bf(iostream)(3fork), bf(sh)(1) manpagebugs() With the release of Bobcat 1.21.1 the class tt(Process) was completely rewritten. The new implementation, however, should not affect existing programs other than that tt(Process) will no longer impose a limited time-to-live upon child processes. The interface was enlarged, but this should not affect existing programs. The internal organization of the tt(Process) class em(has) changed though, requiring recompilation of sources defining tt(Process) class type objects and linking dynamically to the tt(Bobcat) library. With the release of Bobcat 2.11.0 another major modification of tt(Process) was realized. Although tt(Process)'s internal organization was again modified this does not affect exeisting programs using tt(Process) objects. No recompilation of existing sources using tt(Process) is required. includefile(include/trailer) bobcat-3.19.01/documentation/man/sharedblock.yo0000644000175000017500000000323512242114161020356 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::SharedBlock)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Shared Memory Block) manpagename(FBB::SharedBlock)(Shared memory data block info) manpagesynopsis() bf(#include )nl() Linking option: tt(-lpthread, -lbobcat ) manpagedescription() bf(FBB::SharedBlock) objects are used by tt(FBB::SharedSegment) to access the IDs and shared memory locks of shared memory data segments. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) Only the default constructor is available. manpagesection(MEMBER FUNCTIONS) itemization( itb(size_t id() const) The object's stored ID value is returned. itb(void lock() const) When returning from this member, the current process has obtained the bf(FBB::SharedBlock)'s shared memory mutex lock. itb(void setID(size_t id)) The object's stored ID value is set to tt(id). itb(void unlock() const) The shared memory segment's mutex lock is released. ) manpagesection(EXAMPLE) See the bf(sharedstream)(3bobcat) man page. manpagefiles() em(bobcat/sharedblock) - defines the class interface manpageseealso() bf(bobcat)(7) bf(isharedstream)(3bobcat), bf(osharedstream)(3bobcat), bf(sharedmemory)(3bobcat), bf(sharedmutex)(3bobcat), bf(sharedpos)(3bobcat), bf(sharedsegment)(3bobcat), bf(sharedstream)(3bobcat), bf(sharedstreambuf)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/level.yo0000644000175000017500000000350312222576536017222 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::level)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Log-manipulator) manpagename(FBB::level) (Manipulator setting the log-level of bf(FBB::Log) objects) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() An bf(FBB::level) object is used to change the log-level of bf(FBB::Log) objects. It may be inserted into an empty bf(FBB::Log) object (i.e., immediately before a time stamp might be inserted by the bf(FBB::Log) object itself). This is the case after terminating a log message using a tt(std::endl) or tt(\n) character. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) itemization( itb(level(size_t nextLevel)) The constructor is normally used in a insertion statement where it is inserted into an bf(FBB::Log) object. ) The copy constructor is available, but normally not used. manpagesection(OVERLOADED OPERATOR) itemization( itb(std::ostream &::operator<<(std::ostream &str, FBB::level const &)) The bf(std::ostream &str) object should be an empty bf(FBB::Log) object. In that case the value stored in the bf(FBB::level) object is used to set the bf(FBB::Log) object's next message level. If the bf(std::ostream) object is not an bf(FBB::Log) object or if the object is not empty, the function returns bf(str) without further action. ) manpagesection(EXAMPLE) verb( FBB::Log log; log << FBB::level(3) << "Message at level 3\n"; ) manpagefiles() em(bobcat/level) - defines the class interface. manpageseealso() bf(bobcat)(7), bf(log)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/ibase64stream.yo0000644000175000017500000000422112222576536020562 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::IBase64Stream)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz) (Base64 encoding/decoding std::istream) manpagename(FBB::IBase64Stream) (Std::istream performing base64 encoding and decoding) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::IBase64Stream) objects may be used to base64 encode or decrypt information that is available on a separate tt(std::istream). The tt(class IBase64Stream) is a class template, using a tt(FBB::CryptType) template non-type parameter. Objects of the class tt(FBB::IBase64Stream) base64 encode the information they receive, objects of the class tt(FBB::IBase64Stream) base64 decode the information they receive. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::IBase64Streambuf) (private), nl() bf(std::istream) manpagesection(CONSTRUCTORS) itemization( itb(IBase64Stream(std::istream &in, size_t bufSize = 100)) This constructor initializes a tt(std::istream) providing it with an tt(FBB::IBase64Streambuf) stream buffer. The tt(IBase64Streambuf)'s constructor receives all arguments that are passed to this constructor. - tt(IBase64Stream) objects perform base64 encoding;nl() - tt(IBase64Stream) objects perform base64 decoding;nl() - tt(IBase64Stream) objects obtain the bytes to encode or decode from tt(std::istream &in);nl() - The internally used tt(IFilterStreambuf) is initialized with a buffer of size tt(bufSize), using a lower bound of 100. ) manpagesection(INHERITED MEMBERS) Since the class uses public derivation from bf(std::istream), all members of this class can be used. manpagesection(EXAMPLE) verbinclude(../../ibase64stream/driver/driver.cc) manpagefiles() em(bobcat/ibase64stream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ibase64streambuf)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/readlinehistory.yo0000644000175000017500000001654612222576536021333 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::ReadLineHistory)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz) (Editing input lines) manpagename(FBB::ReadLineHistory) (std::streambuf offering line-editing and history) manpagesynopsis() bf(#include )nl() Linking option: -lreadline -lbobcat manpagedescription() bf(FBB::ReadLineHistory) objects offer access to the history maintained by bf(FBB::ReadLineBuf) and bf(ReadLineStream) objects. The latter two classes use Gnu's readline library to allow editing of input lines. The accumulated history of these objects can be accessed from the bf(ReadLineHistory) object. Since Gnu's readline library maintains global data there can only be one history. The bf(ReadLineHistory) class is therefore, like bf(ReadLineBuf) a singleton. (Gnu's readline library does, however, offer functions allowing programs to use multiple histories. So it would in principle be possible to design a non-singleton tt(ReadLineHistory) class. Since programs normally only interact with a single terminal, there is probably little use for non-singleton bf(ReadLineHistory) class). The bf(ReadLineHistory) class encapsulates history access. It offers limited facilities: either forward or backward iterations over the history are offered as well as reading and writing the history from/to streams. The contents of the history lines and --if defined-- the timestamps of the lines in the history can be obtained using iterators defined by bf(ReadLineHistory). includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(NESTED TYPES) The class bf(ReadLineHistory) defines the following nested types: bf(HistoryElement) The iterators made available by the bf(ReadLineHistory) object provide access to a bf(HistoryElement) object. These objects can be copied and assigned to each other, but user programs cannot otherwise construct bf(HistoryElement) objects. The class bf(HistoryElement) has but two members: itemization( itt(char const *line() const) returns the contents of the history line to which a bf(ReadLineHistory) iterator refers; itt(char const *timestamp() const) returns the timestamp (if defined) of the history line to which a bf(ReadLineHistory) iterator refers; ) bf(const_iterator) and bf(const_reverse_iterator) The iterators returned by members of the class bf(ReadLineHistory) are input iterators, pointing to bf(HistoryElement) objects. As they are input iterators modification of the history elements to which they refer is not allowed. The class bf(const_iterator) allows iterations from the first to the last history element, the class bf(const_reverse_iterator) allows iterations from the last back to the first history element. The iterators can be incremented, compared for (in)equality and offer tt(operator*) and tt(operator->) members, offering access to, respectively, bf(HistoryElement) objects and their addresses. manpagesection(CONSTRUCTORS) As the class bf(ReadLineBuf) is a singleton class, there are no publicly available constructors. manpagesection(STATIC MEMBER FUNCTIONS) itemization( itb(ReadLineHistory &instance()) A reference to the bf(ReadLineHistory) object is returned. If any history has been accumulated it can immediately be retrieved. Using this static member will not affect the way the bf(ReadLineHistory) object handles timestamps when saving or retrieving history lines. When initially constructed the tt(ReadLineHistory) object assumes that timestamps are not used. itb(ReadLineHistory &instance(bool useTimestamps)) A reference to the bf(ReadLineHistory) object is returned. If any history has been accumulated it can immediately be retrieved. The tt(useTimestamps) parameter defines the way history lines are read from or written to a stream. When specifying tt(true) the history inserted into a stream will include timestamps (which may be empty if no timestamps were recorded). Likewise, when extracting the history timestamps are extracted too (which may also be empty). When specifying tt(false) no timestamps are read or written. A mismatch between the actual contents of the stream from which the history is extracted and the tt(useTimestamps) parameter will results in unexpected behavior. ) manpagesection(MEMBER FUNCTIONS) itemization( itb(ReadLineHistory::const_iterator begin() const) An input iterator pointing to the first history line is returned. itb(ReadLineHistory::const_iterator end() const) An input iterator pointing beyond the last history line is returned. itb(size_t maxSize() const) The maximum number of lines that can be stored in the history is returned. After collecting a history of tt(maxSize) lines, the next line entered will cause the initial history line to be removed from the history, making room for the next line to be added at the end of the history. itb(ReadLineHistory::const_reverse_iterator rbegin() const) An input iterator pointing to the last history line is returned. Incrementing this iterator will access the previous line in the history. itb(ReadLineHistory::const_reverse_iterator rend() const) An input iterator pointing before the first history line is returned. itb(ReadLineHistory &setTimestamps(bool useTimestamps)) xThe current status of the timestamps usage is set according to the value of its parameter. When tt(true) inserting and extracting history will include the timestamps. No timestamps are inserted or extracted when tt(false). It returns a reference to the updated bf(ReadLineHistory) object, allowing constructions like (assuming the availability of tt(ReadLineHistory &history)): verb( cout << history.setTimestamps(true); ) itb(size_t size() const) The number of lines currently stored in the history is returned. itb(bool timestamps() const) The current status of the timestamps usage is returned. When returning tt(true) inserting and extracting history will include the timestamps. No timestamps are inserted or extracted when this member returns tt(false) ) manpagesection(OVERLOADED OPERATORS) itemization( itb(std::istream &FBB::operator>>(std::istream &in, ReadLineHistory &his)) The history available at the tt(in) stream is extracted as the current history. The existing history is removed first. The tt(useTimestamp) status determines whether timestams are extracted (if tt(true)) or not (if tt(false)). A mismatch between the actual contents of the stream and the tt(useTimestamp) status will result in unexpected behavior. itb(std::ostream &FBB::operator<<(std::ostream &out, ReadLineHistory &his)) The current history is inserted into tt(out) stream. The tt(useTimestamp) status determines whether timestams are inserted (if tt(true)) or not (if tt(false)). ) manpagesection(EXAMPLE) verbinclude(../../readlinehistory/driver/driver.cc) manpagefiles() em(bobcat/readlinehistory) - defines the class interface manpageseealso() bf(bobcat)(7), bf(readline)(3), bf(readlinebuf)(3), bf(readlinestream)(3) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/bobcat.jpg0000644000175000017500000037125412222576536017511 0ustar frankfrankÿØÿàJFIFHHÿÛC  !"$"$ÿÛCÿÀ³ø"ÿÄ ÿÄH !1A"Qa2q#‘¡B±ÁRbÑð$3r‚’áñC¢Â45Sƒ²Ò%csÿÄÿÄ9!1AQ"aq2¡±Áð#3‘ÑBñ$4RrábCÿÚ ?ìÙÕXÊ¢Y'*‹8 Øi¶ücŽæ~Î|Lôyë%;ëš Õ‹^Ë}ŽÇ#ñþª1ø_P±2$Á5!õ6Úç‘þ—Â_øMÌb 4žIu,H&÷±Ç”„g ezÑ…+ ÉÙg\Š¿.È¿…U7^(‡•ö½ÁÙ±M DuSb»› ë‹Þ{,sÃ,PyžÛ…ï¶9GˆNg—tfÌôÇ“K…°Ô„=ûZø®zU5mÓ_Äöù,ðR¬5RÄ êS¸m€¾û`újå†@YÙnl·;c|Ò‘ãð¤9„%&ª¦MZ£õcæÿ¦*çf:Q é3Ø~;÷Æ4’M?Cm>Ért*lñI#{°úжö”6³ ñÏE\ QJâPyùO¦5Éüb°TJªR“)²ßaúá1OkøXa7„¿ñk—G˜þK7Ä©‰XÄ5 jÚÛcã$‚“ÄwD–:<è(ZÉJ€…ÿž×ÜÛßAÿŦs>SñøBÛ€>[‹cå³;fŽkÎtù¬(ç~Fö°Á7ßÏäž—¿S¯…IãLŽº¡¨0W™ ¨ÈQ£ÒP0õÞØä,[OM• ‚kúþøŸ4¨š¢©ªkª¤’vÒu¹ X”;ÚÀý0;§MŒÅH 6o`ß¶6²Öo?E †ƒQ°ï²Üqú_õÄNæHYJ&’Úà)÷Û}ñ‡¨º†Ÿ<~bI»þøÑUÀ:ZÊÄê[ŽqoÕ"MDyÁº‘Ææöý­÷ÆJì!uÆCrâäìq¦ÆÀ‡#kißõǬ%‰Ù€US°çëƒÏ@7ìÖ±RÄ_ûciæ ^ò\ °¦"xÜMX “§öÆXX$—ÖO呯ãÛïƒ×=ÎŒ,m£o2rHõÇB€>¶%´ùnm×ÛÄt¶¢Íp"ÛöÁµ@ÃÿQ`™E—Ê ;ò-ÿÆ€åúZ­˜y[RÞÀòqŒ‘3 ªÃv’E€ýAÆ=ä¹’BŒ»ì6Ù] ‰lI]½®?{àV¡b*¥\ù†«Ý¿Li/PD:¬{D¶ mÖF$òN§œzÐʦÊ-a¾ n]ìPýÆí¥bЀ­Øj$p1ê»Õ0wcÎ47ÝØ÷8€%Hÿ-¤eNÚÄØú_÷¿Û©ŒyH³1¸aÂãÕsÔÖÀ0Q°?Lm"° ±åmˆCPÂ3°ù¼¤Ÿë‡>¨øÌɉ¤øÊ i•AÜ”!·ä\a8Œhر¸Ø{ûãhø+i m¹½‡^ý±IO+ÓUGShúd:Úû•76ý?|} ઺³h«ãN•,’G6². “ͱll à¶>x+  åv<§×oìöXa)º‚%,»@=†ŸûC~„úâœðsƒ¡¢éŸjåy²Å'Tˆ¢«Xå!v Ê…[X€Úw·<€ ªžŽ¸Ó:f‘ÒÇ ÅÓªš)Ú:³É¤,àaÀ½·µù¾QWG˜d•U4õ KRVÒ± ð°p}¶-q·6[c§øV 4f’J’÷–(îWH#·òî-bGÍcÜNÖÚM›—(/-ðè¢ñ)©y*«(&‰aè««GÌDí¨‚F’ê9 O8ʜζ Þ¥k2êŠL°:âdœ¾‘¨ô@5¬n6 ûaʵQ½44²SÒSXÆV"À£3j ¼Þ¾›aUu8­‰:Q¬b•ž8È™T.£È'M­«p1l¢—’ûa–Ã41É]GM–KKKyÆŠ‰/䑘Á®iç~p,Ô|n¡(+§Y%¼¦kÉMrC)f ˜ÉX“{í|E–çRC->m)Ëå™ÉF’_,ªw ³-¯bEÁ¾ ¥yºµÙe9iëâE!âŸÊ…&ÍpÄ…"À‹wÜßR\kO³É*+c-OK—Ös±P¹Üs±'ÔVÎÒÐÏ;” ñ4±h6º›‚mµíkÛ «ZŠIà˳(⫊Œyæ1ÒIPÛ öïÍïˆü;•å¹u²(ãʨ]EK¥9®¢*€H±°ßVÖ›ßF^ÂË®K!¨!›á vbŽÚL-J’I¸ÄàFCU4F…%te–'q­K ò ˜‘`GÜ`§hY5É)‰ÔGŠ)0cqÈÙ"ësõÛjhØ'+DËêòêO„Ü&¨±+ss«{(õá¯Å¯…4/ÓKÇM)`c>U±'¾ÆßqÈÛ„óST=@r*Yz…¾Eßï°kúŒ UæÇIâ(Ÿ5ÑÕ­sºƒK9©c×¹/·ÌxÜ’ Û‚NZZJ3 ôKNH£fV³Èí¨• v¯~O8®Qª¸Òኢ’•¥žhãQv¾¢.v½¹ßüQ_AS–ÓMñÃåHÒ åä…Ë1N¢T{xß%˜Û·!TW Í-9I‘çiu¼€ZÃ~8·Û}ð.Y”Uæ9„0Ñåí$­ªPîI["ÞÄðå}Êíäj“ ¨cX´RÙÝí© ±»òÜõÁ¾ ª¦Ê3åÌj£©thÊ•%têbUÎÚl íÎÚº+@­•ü4añ +Æ ÖŒ¡F¶ìªu(±ù{qHË3‡wêYéâV*RÝ5}¬m½¾Ø>&zÚyë‘:ŒÉ tì©½Ïøˆ:xØþ¸CTÃ_œ)ÖAuy²™È$†;ñÍ€ÚØ0¾Øh•§øÂ°8‘Ĥj²‹‹›óèIöÄ •VD€ÄGŸUÉÜÜO°l/*”ÕG¨”ÂnM¶Ñæ=¼§žÄ`utx ÄÆ4G^í¿À¯>»a“Vl¾I4¥\ByÝ¢ÞÑ;7Öê» ü×àLô°ÒÆ`ª}FÌ\5®ò„A¸°ºïmýñ¤S¤1—1G9ô…I,>]m$i’á™?q¿û1ðì0•ª©¨1ºÓÆB6ØìÌonä}‡¶ÍO4®ÏðÌÑ‹0PI¾×¸á‡é†yŠd´ùZô ˜M›^ÝJ¨Ý¥`ñ%ùIÛ½ŽÆÖµ÷ãÍ'Ê h)j^—T ¿–à÷–SO%p¶S¢âöþbyÁÕ5$ÖÉ%2BË{¹¾Ýý†ʆ”ÝT4î.~ßL0 Ø+º$ Ý¬ƒƒÍ¶úŒf%FŒÄ ˆæÖt…{©B,m·ÛˆìÏÇùj¼IXþÉ¥ŒÒ£r±Øt€-ÎÄþ˜ð*¨ðnezÊç˜JÅ™tºm¸{áSã¡éÚYk'.n·S¨“ÚÞ l1¯ñ¦Y•e¦µ2ì?"6:˜l{û±äõù5jKKñîTá’icŠ>ð¬PV×I˜ªÙtÙ.xûbµøý”,Þ ¨ž%BQìßö'»ðñ+1ͼQ55I`…ˆéžvØŸ×Cñ²¸IàÊÈ£$-k íc·×c:m<žU ½¢œ‰`˳Ԩ~ø’ª¯ÀÔñõƨ‘•ËÈê0%:æ Y†½‡¹¿úPr*–ð߇Vžª©ºò­Ú0»î6{‹ÆI,•Ù|­Øàöüã™®Æð¹WV̺•4έá&I¨QB’Œº·Áõþ¢©Ú-Ø6Ç/ͼoW༰VGFj)à!gUxÀõÿ±†¹Oâµ_Ѝ„9>Y-;¸±yPƒk‘q~ÞøÉ¦Ó½›åÂ:v£º\ÿâ^ ¦Àµ4³K˜Ãq¨ÜÜq·ÓÎ9µ¶à¨)î}±÷}gá]'‰Õ¿õ=eUh/vŒÔ2¨öØâ½â?øgð5eZêrê€IC8>„êßíŽæ‹ÅtúXyr“þƼZœP†Ö|]D(&p7󅶸Ò[Xy•ô‹yw?{ãÅ4Ò‚·±÷çÿ“ˆBr¬SN›±6µñª»Æ©̶}½ñàvÂÄÜ žËó¾7žUi®,Ñ¡6¬"ÿSß CU0²+™¬ {.Âø–¢5é2‚»ÙÃAa°¶4+iCHÂåB¥‡;{{Û;¹A:¶åSÕFãûþØ„•;Üwã, ¼£æ=±ë¬GÔÛ„ÈÁXéV;’6b2«\+¯6ã>¢XÛF’ÇRÿ‡åem$‡±µ¿®#I%ÖŠ50Þöö¶$˜³ ¤ºüšÀ}1äq”“ó[¦ÃWr Y%›ôËIÕµ®/ýñ³À¬Ž¦ÊàØ½¶>Ñõó‚,/Î20Ä+¸é¾ÖýÇïˆCRSE®,EÏ7Ã3l£5¥­hR¡`7h‰Y‹0?U6ÛëÈÀ'ç0”+yHî=6}CA}ß­Q¬¿sdš®–š©þ`]hOL«_Z·›k$wb7¶;­gKE=2» ¦ZYjæê9EŠ%b‘É«IÍ©HÔopO+ÿsúZªŠ¦¤Z9¥˜õ ]•£º¯ø¶•‡ÿXúg¹¥LÒ“ôb GêH!dשÇþJ# ¢ú›·|r³cÛ#^)pt*ÓåD*²igäd¨¬Š-VÓg˜4®£¥tìoëÆ'|æ¦ :™3ÚxhÞ8Ù£¬¦“¨ÉKpI$éÙ·Qµ†+u¹e6mVe®ñ ’µñÑÄ"*ërªdm¬ µ¶±@»ÛUUåuk4b¦dááJÐCÎP%•¬# {Xò0«'ȵÅvZ²ÈiÞ(©é/ å´¶‹Xg!t«×{€EØŽ[Œœx~‚|±,õšÁ“âàÒÍ!`ÇYmÇr50¶þ˜]QšÍqœÕ×/Š%=\’5¦,XôܮŎ‘º½ˆm¯lC›>bòPüu] #2–„COb­¤F]K »Ãƒ°ÁiG–-; ‚’’œŒÓ0ÌäÕ THGRr‰6W,7ò¯o®šn¬Tù„´i˜ÍmQ8Ò &’y¸7qÛéŠvW›6[Hí•æ•µÔð]êêò"9kiÕo?ÌI ¾ÂÂÇå~,¡ñSÑe9Fq˜™ãtjµDÁŽ—}l¬®HqÎ&>z¾c:Ìú†‹/—1Ìä4‘4«0Cù.þ}%EšÇb7½‰âÖÝÁ¤Êê$Ö•RÒU,iä´—¿ÈÄßVãœ{X)29Ú¶³3–ž¿.:e fboem:‰<NÛnùSâ"ùaLfVç+në܃¶4¨ÿäUËè>ªòŒZÙ ˆ «Ú…îŽ]¦Ì…[4yd4eK>£(Òk$ùT³-¿—‘ŒÎ3¸*U"ËóJ-:z“Ô®bâÊH#Ìx;{b¿˜dù‚ÐÍ] sœÎ®ƒT²¸h U-¹d±{Û{ -ïŠå±:ô%:ä=ÃÓ4µ”U4Ô°€ÚÒff2(²*Æ …°Ð·-arHÞøVÏ–¶m@þ"Aj´ÉIÎ¥°2JT†±$©,n¶ › ¬2›7›øvUâé³…‘i¡’>œzÁ ¬áœ‹}½ÆùåluiIE=Lo"´TÑ5l+üÂ;ニ"à“~%²F©çµÃ(‰…E{dCid4óȨµÿ,³©¸ØïblqV¢Ï+jâ­Í!­žY«)c†ˆM’IŽ@»ªéÔ±k>cɉL«Qá·–·4 ¬¥«éƒ$èŒÒFe‘Ø‹ØÄjfú0Ûç¹VYYð³Ã/Áõ¨–™ÃB¨ËmE‰,IU>c¾þã m‚=òsÿEüKÄ­Njk$iKUÅy%Œ‡Q­˜“ªÀo°±'lTó¨'zxdžò‘´ê‰r@$ìånmvŽØ»BÕ4Ô’¶ZÌôuq2L†§Ë¡™Ž‚H¶ö¿¯®(9Å,Ç8T™êcŠÌdPàCkÛP‘~ޖŸ¤Ð™nìOâoæpBŸ ѤHÄpFÌB[e ¤ìI`I6¶ø­WM3Lªu‡óF<±Ù¯Èo{ ÅÎ ¨WêžT…i‚,e"Ô4*ðtÛ鵆xóSç/ŠJ…R C*rÄvQÏ~>˜»ÒtVÛ’²¯.b•£I÷,HòÛ’£Øm¾5Š(ªuÉ4©P\ÜŽ}Ô[þpfa”×ÆÌ„:!YÂ"-¹"Ü‚9í‚i²Y"lºc4É"‡+þbd·×ƒÅí÷ÅÍßLNBü?¦ &AYª¦¹I~m`nöú5È㊫12“¥SN’¼f)C*!ÒHÜ–bmb6FõÞ*”Êiªš™È©™<ÁiåhYر¶ƒ¤ÿ+[NûßÓ ³,¾¿Âe´p…žYÒ«âU:Â! ®“ó’×¶àƒmX¢JåÈv¤'Ì)i¥®¦¬Í#©39‰ã‹R:ŠÞÛ§Ì/`nwº喣ÄsSå6y…WZ$E¹P6 ì ·{È¿ãÈ'­¬…í4®ÑÂÌÖP£cÍ€#ÔÛ×ÐÒÐIG+UWÓC+Î-TÉ}VPáSº÷È7űЉ-#J´Z†/ÓŽ?Ë^º¯]Í€QpZæû‹LižºÔGà LY8êZ@‘ap× êf6¿˜^ˆbàm.nö½·Ü\_“¶,9‚×´ñê¢ø ×1ÃD‘õcP.TXƒ¡ÔnÇÊú$’´6T¦.ª¬°£·™Ø€'bMín6õÄ‹»LgIBj("YÒŠ(PtÖG!ƒæÔÀy76ûZøc—ÔÍ—S¼2åï- Òt%!£WX[÷½Þ×{ ¦¥Y(¦†’v2ÓHee!ƒ[ccÇ¥½°Ë4¬ªšžx¾.IäÔ#Czzeyó°1—¡¼IK–EAI&\ì,Q0Ff)wF,unIÞü=pn`­+ü5éòÔüˆL©È1³.­ÎåÍ͈¿#Œ_ev©žq9 P˜ bÍæþ`ö±Ö*zQ»Gi"Mª<Ú·Ëî7çÿ|2è…¶8*«¼9 ¹l“Ê> õ5ìUÎ’&ÜïßSdô´ô­W=KÇm ¥3ÝÕΫjí¨»²ûâÌÓÿ¥£†9$„ \3z”m,ÆßV6ߎØMDœÕœ¾äÿ˜} ¢=a.ÃHõ¹qþ-» &<¶†}OI6ªZt~•$Ë»0·<-Áß óyȨ3­*ÆÅE¼Ä¨ÛI \íoLYsÐôùdT¶cÓ{#© ‹.¦%IâÛÍ”vÝ,4Ô¦©]–v»H7m†Ä°’}IÃÚ+´-¬Íçš`ÐÅ*Ä"nF¥f;l9¹?~øß.š¢IE‰„É!`gQ¤¡¸½»›Üq¦Ç +¢Žž”³E ÎÓéWPz¬ªA;j¨ãßôÆM:Õ$1#4•náRa¸ŸñXpWÄ2h6ª•g‚Ö ¤ª’Õ@t¦Ÿ1ï¸7û$¨š†;iˆLD¶Ô“¢ÛEî ¾¸e–×è™W4Žd ÁÆ7CþíbyÚÁg4N*~ǡ՞$uaÅîÅI<ëéÎá‘ö{K@=u³ÇO4ŠZ5cÓˆn1ž'Íi䮞“/š:¸TéY´X½Àó.Û0±µ¯é€W-ÓHU(ÚjÆ´p›Ú6Úç~ âÜàJïˆ@#E”û(½Í›ÒÜâ$“'`’É[%[Í;´·7~²{ñŸÓSM ’’zr Ž ³ù¬7* ¬@ÞÞ¸.::ZjC]$rM …VœØWeöÒ./êAô¿¹nV•õÓÈ좆™–?0˜3¢éÛƒæ]¿Êpï¡fv±S©tª¼0ÐÀ4–q+DŒÊ½ì <öCÖ’¡¤i%œIP CÜý.>ø+ÄU*õÂó4Á3?“q¶ÞÜ_½±6X‘ÓuM<±~A, ¿”;wÛSmkñ€…h‚!SlÒT±aùƒÏ¶’Gï÷Ѫjþ¦¥BkòµÅ·¶ûÞøgtõÂ’9* ]D‚:Œw¿Û‹E¯¿8 ¥’’zˆuš2£¨§™N¥?âòß”S+ON•†›‡(-{›Ûm=ñP«˜€Ÿ—Vú@Üo¶%‘*Œ±9h‰µ£Ü-÷ßß}þø––œd«@ FÒ(%[MÔ_©Äj¹‘åæŒ4ÕPh™-"ÃSXXƯ¹_[KdSU¤±‡¸²É öÕØÛÔvÆTf¼J4’$i#I}1‘p6þm—œmUð3jªXÈÞo—PÚÃôÅT÷[¾’L­uEɺØ(¹Øv7ÆÑÆÁAg@RË°ÚØ/E?X·XEÔI7qô6ãÖTj*^(gHâSw6ò»A·æíú[î\`M%•œ »1 zÿVÆ`¿ˆMRTE jÄÉ)¨(=yoÓ‰L‡z¥ü8Éhszh¾*Yuò#LBŽÜ[f¸c¦fÞðþiBa’š lT²€@°¸·{w÷Ç=üV5ð¾gK]Q$¦švÚM?-·½ðû)üQ¡¬¤Jxâ¾`ê”î7íí·ß?2ÕfQ̘³ó8q(^ vðâL™d¬®‹ éɨþjÁ=ŽÇïÄyŒþ,zD¢RôÈ8¸6{Ž]šx_7Í*¾) §©‘7""Ç{o~Üö.:wàÆQ[áêuƒ1òÊæPÄü×ÚÃéµÑ‹R‹¹Upƒ—˜Ý´ŽøŸáÿJŸà™Œ”Ì¥¾ƒZÄ^öÚ×8ñ"§.Š’ xäéʇRÄÛ³°ãýqöö]EL"eè¡<À÷ÇÍ_?‚9¦y㑘x^©)¦ˆõî»jõbÜZ¼yžÍB¥@Ç›hîšÍK‹4g?Kßß-ðoIø}W’flj ´Å¤ëË·ÖÃ_À¯æ1u²:šñKç·$µÈÿLdͤŽ};xŸ õò.ÏæÂ¶ô}XÑ(b -Ç:{ U2S¨iTw¾*> ‡8¢žxóôªU}Q»¡î?ùÅÐÔ+¥ŸÌ§ÒØàePN¢yÙãQ3åøªñU›R „Å,Ѿ¡}Èìmö7ûcæÉçX-¯Ì¡@Ûõç ?ˆÿ†¾ ñ},‹˜e‰hY£LŠħ×þ+~æñ£¨a&_PÅ)ªEÔ06µýïêocàšÜ/ÁÎÖ–xå h£¨mE¬¬×‹ãÍl¯Ô+ÓˆàソLL:O§•¼ìX€5pÿ\hË”ñ0*£êÛÜíÇé@ø4sêD¦²+t˜Ø6<úãБdò,lJÖ.¤m«mû÷ôÄŠ›JDÖKZäÞàñôÆ*º¬ÒY”êUIÛaÇßÀG©Yµh½ì@mƒíÈÄ^EB´›ªN« é•‘U­å-¾ýùã{ãÆGy´¦F;Þ×?~17ÊijëçO¯oÛ§QoÔ7¾ }e4l†ç`qᢤ:ÈÙvÜ⊀»8;€Fã¿ÓÔ3i‹…ö?|M5ËÉEpnÞ›öý1Ÿ)PQÈ㆗ ‰‰Õ¤èý9Æèå£!j'UÀØüýñ‹y -`ª6õÄq;º+ÚÖ#Mí…!ì„;‚¬.ÎÛï|E¡X™O¡ï‰åS…‰®ãr6¶!e.Û°_6âØb>A‰!Šî/|xQŠZByÙoΈ"€ì °n8zúóoÓ­:JHÒW@¤ÙÂï¶!YŽÊ²ÝæöÛ¶•MLA'u`~QLm¥I¿˜Üݱ±VŽÊÁ‹0µ­pÞø„#2,%Gp/‰Àu ɰߪª²0Ðv*¢Ço\c8XTMíÅȾ! àU.àÞÆøÉ<Ášè Œ—¹'ÓÏ«Pc¦Çb/‰#å˲°¸}û6ØR+òƒówôíýÿlo"¡v-q©A!O&øßRK©UØ µ¶úã@ÌÀùv°ÃÏtuØn[Òücɤà*‹AbÜïûctf Z3ua¸&ÀØlw÷·éb ³9Œ)]Ë €Ø›kÛ…Ïðηá#¯Q8ƒLªKs`mFvçÓÀY‚OLré^UœŠ~¡! K°Sµî4\[{ ·||Ýá*šj/SI^#4’þK¾‹‹0$7ƒ¤ûŽÓà³#Tä T”É$7 Tò³YxØÜ_{¶ý±‹R™d&Ó;…$;…5JŠd—Xep Ù!½Å†/ÜÄùƒG]I@ié>1—2H™aø¬½¢ë̺u–R†Ìlañ]—ÔçpäyFJ«QP¢£2h¤b½Š•¾ÁÁÔÄ5ûÜúX(—5§É¦­£ñ yž_ù’¼Ô5R !cÙÙö`/æ_aéUüA‡'¢¥ˆMK Pæ,«ODÌÊjKCHÁˆ?˜ñ³£c~F+“i‰&Úçõy6SQG•ÐfYñ6"9^ª¾DÌgFÐt«·U“km=Ÿ׿Ôù¼0Å•%<M,Áàbʲ™µ \îjÙ·¹Y˜d?ÃkéàËü7Ô­ŽO†¦§ˆÃwvrß:i c-÷ÙNx—9ðóVA–çí;VªË-U6@Ò^" ¶ùϘ3q·;Š2Ksà¯u)³¯/N&Ê!ª¦£¦" ºXM@iH!ä‘Ë_I¹"ÌvQÀªs\Òºl®‹.¦h™š–AÒ«0´ÆÀ”AU>cßp+Ù½gŒóAԢ˨2âšLº£š™A) >³³$‚»l5Ï)§Ë|EM%-|5±¬=^”EÂØê²iÜ‘³no[Esá2E«6­ðÆwᬂ£7§ A,Â9²á ImIuù¼­rIÛóÅ9c©hÿõ EªÇVh#•]Ù¤óê£ÈŒý,.N÷Åø¾}â*Ũ ù¦ ÙzF Ù’22È×EãmôÛGGürº:ŠêZ<äeò|]@(ù\÷Ûƒ¾ È(ß4«–‹2Ë²ã—ÆIY#}:<ĪÌ ^öä pN'޲zxg«§Ë †­íðæIò²0îšÀb{Ü{û@ñ lÇ+–7‡¤)Ј+N«#C „#ObÚlw<–µÆ+pf#ô"êt©jhÔ0P} ò0%¿O@pó/‘UC[ÀCÂUþ%*‘Ô L‡HE¬þ§¾üáŒA_šÕæÉ”™²‘½uUB®à^9t†Ò¤µù,¹8hʹeRðŠ}3CS˜ÇV*Jˆ •ÔÄ ÆÚ½Ó|ü©©"Y3JŸ‹©PRXPÌ’j;·”‹)Ók6þa¶ã _Ã3‰(©àI¤\¿*`ú˜’Ö°e$…XøÙ«hà¡ZLí3 ™×HIiÿë]ã$«ÀX#PóÇͰűžîP®Œ®‰òYSÄt•ú+i+:t¦6/ª9Y-¶€t-ŽÛ°ìq`¬§š³ÃðµrÖf•’»MP²)ävW”î@&?æ²Úü0²š¢—0Ë(c¦Ž:ªJZ–ÕÀ~ ¤ªªd-¨^U;Ø &äÜŒY(hëü)S^ùuhë=;DáÙTd*4Ô5µXZÝ´S$ÕSìN¨¦xŸâ²‰¢5rÇ,ŠTiι@_"ïÅô‚-Å€q„•õ4±fo‡ž&Œ$†YQ_Pµ÷yÉa¦ã{𠯞0Ëh§7Å 29.H}Cù‰@@¯}À¸˜¥WÒšÙ_;Ž›7QåI#ŒD7[ƒkrµñf)RäKk€Zir©çjjX*¬Å5Növ‰VÊ¥ˆ‹5ÍñfSÕ;Skš9_ç Xçc¨ïÏÛ3(ª'•èr¡ t´ñhN»,rUh»–ˆ%ˆ+s`‰ÅZ¢/Îi讄Ë{-íroÙ¿^×¹wÙ#ØÎdJÈ™)bge[NÌöSm#@êÖy¹¶jKÕN" ¹<ñF4“¤rA$îˆúâT¢VÈMGJ¢Ä’N½"íº‘É,Û€7û¸§«Ÿ3ñ%ÆåÔ‘ôd5 _Jº-Ø÷±m{[~O8–Y‹—„²äðÝMNcÇ1‘#XnC‚@ÔÜ\(M7½÷ê[±²’ÓåõœTBëP 5u&@#%Æ››.­:¬°ÖÛ‚E˜ÿêøé'Š’¦:6¹\(}¹Q½‰‹ƒ¤\ßLû5Ÿ2­–QWPG]ºˆ¾][ 6ç± Osh³j×™¥¥‹¦!§…C¹DÒefØ›o}‰'Ó §®D‚0¢MÁ6ïe;öß|XóÜښƂÜI-¢‘‘õÎÌl7 o*ŽvÒq„4‘=M|tÓKsK1™THÚt«j6–<÷ÄÆŸÚd}›eP¢C(¨?M¢ŒD$Öá—‹|¦Áüã}“liN’â¨Eùˆ?˜K)ºƒÁnonI¾ÛbQ5-<†‡âÑ:Ä¢0m@“Åì@æÛ’xŦ©éhŒqJÅRš)Ö$¨Rfu$à²ØmÁç’îMrÃSa¢ËºÅc¦ÌjªÂF…cRÚáTµÆß±Àpe­T9ToäF°îþŸM¶ÃÌê?‡¤†´×´E˜¬Š,d,È·]r–ß·aµ·I˜gqumG ¡PBÈ&$’8;Ž?|Ûè„5TuQDfDV³ÆÎ¤¶ÇŽ1äï,’êÚÃR™5yîn6äv"ÜÛÔgõÕ´pÓÖº³DtÅ'ó"ßu—çƒÎ½C¨XÎè$º¡;ßnO>ŸÛ¾ §-èA8M`k(,#ý.>÷À¢ôªAí"‹‚7°Å‡+Ïèé¼?>X|9’ÏSRìã0ªYLé«ËäüÀ‹m¿óõÂm$Ç‘$±Ýlmµ½ýï†NÈkJæs OÔr ÒM>„ßcÁ_ÖǶäæu‹S%ÙV-Q‚B€nûqˆ¥u£uë¤Ò.cý0D©ÇDR]YHÖ-}¬>‡‚ ea~I%š×$݆4ë×­DЬTj>_Mÿ[਄>¹ƒ³‹êZÆö]½0bº´B²zxã]%è^5cÁ'¿$­CÌέ¡1 .-èIÆašSE׺7.W§¤7¡õçëlf!µÿâ/%øïÏÒ$ž"lŽÛZÖÿbøã?†y™|ÐUÖPT?P]¬¡oÅì6*Ao}[c¶øÚºt¦‰i;n8a‰¿hcÌØZ5h”\wÔ{íß{ãÃOPôšG‰_"O+ÇŽˆr¬®¢®H§‹RSÞÎMïúø¿nø¹Öes5=5]#]à7`x6ÁSÐ,6Uü¦Q°ß ²hL´OCpGûõÇ#K)Ûg=g¥õåuÐOB•1J¥ó ð{á-e5ddÄUŠ›qlÊßÂÞ%«©ŽQ%5XÖTl ú_ xÆžŽGš´$j6{þøìnQ’}Ù)â{WLéŸ ‘ºH€‡w¿âÃgÀ¿ˆ‡?Ê¥GW)iQ?üd²·=¸ýñôöAø‹çÙÁeó#°Õ7qÈÅñÓÂTÞ.Ž¢3ª^'Sò›ïì~øëiå 2ø“IölÁ“Ë[_Bþ"Ó'…a̤+;Ñ z‘XoRÿ®.o‹²LÚ™*²Êã$L·[°íÛ¯ðs•~ñIÊsÈÒzY_DS”ºº6ÚXp·ôaÜwœ¯À™6FÏYSBZë A·äëô¸ ÷bå5Å'q+“gtÂÆJÈÀÒKZÇ7þ%3ܳ4ðóQ‰aœ‡ ƒ´» ëæý±õKø{'ª„ÓÕPÂèyÔ£úãŒþ2Ã^_PÔfþ­–‹1 ŠYñLmÀ'ä;Qê1_†áƳ©ÛAÒaIÙñiÌAO ›±íŸ)Í¿Ó kòªª Þ§.¯SKSOhåWKY¯ýýxúce¥UŒkSÒùüž`»üÄwíèqîÓO”u*€ã§:™Y1ˆE ½­¿ÓÛôïM;Â/-ï¨Ym`oÜ6‰#øKH4}Á!¸<{ßŽÇØ`yéµêo0ˆ.èÄÆýû®vÁ¬·”ÆUI±¿$ÞÇ÷ÄoM¬ŒFÚ‡§§í‚š¶:—Nësí·÷ý±˜Ý¨³Þþ‚äûbU #Hìm<“{ܯéQ$vV¾•bËÁà K"2£J Y¼À–ìß2†Ršé’Àéäþ0À5™LŒË *Wrn7ó[úíˆÅ€Ð¶ÒM˜‘Æ6XÑZÜ:Eöõ#÷¶1Ð0k’Äì›ï€WŒƒ¤þR ’C_éÆ<$dT·”Yÿ ÷¾ßßJ­ÒöòÞüã¬N‡*ö*àÝpHFÊv,äèÙl¼ã$¼„$£AÚÛ›ñ‰•m¡íT+¯çÄÜ}ÇaýOéˆCQ%Y,}lx~qí²ÓTu)ö;FÅ팜4B·R€Wûß°õÇŠ#fÐΪ@½•xöæçPœÁ£’±ç‚™cŽCsþO_ß|@”äÙ™UU÷ @Ü~¸ò%´";—!x;[˜Ã£•v°óík{_b>™f]h4”q‰)1’µìlÛôõÇ"êt«Ü|Åœmkÿ¡ÆM¨,ê4’6Ü÷Ä!-=#HIUÞçVæÝ·çÖø‘)çkt:8.Ão`§îבM 7RZ‰>! b8Æã§bY¯Çr-Îø9U,ò1Ôm¿”› ûàQ -F­üÆÌo]cT2#u|ÂÖòúo‰X2Kue*P Èo¿ÜÛîq‘S1{ ¤¹¹û}¦¬Ð´ve&5MБeäïL ÆK8!ÁØzúor~Ø"8µRÁÔ #h°n ùù8ΤK¨éclÛÜ’Ùýp£º—+®‚XØØl»úx~Øî_…¹…&}CPµr²¹hZs¬†VIÖ·ÕÚÌx¿ëŽ%*’ņº¯Å°ûÀ9›äÞ ‚MX§H,-r=í„ˈS;Ô_-s5$õrÖÈÙœ1 ©ˆÞ÷ã׿¶.¾ñ[ÓÓÏáÑOIQIQh=i`¦ÌØoZûÞÝͱHËÖŠ¶ )©ªJ¥Ç˜1 µêQ°,€}ž7Á³KEM.yq™c*ÌçHY~VVdâûvòØï{cš¾¡v‹žsŸKCY]F¹œ”4vè˜ÒQÔfÎöÜX,Ø3$©‚£#Ž óúˆeª£êäòÌ‘Í ìÈË $Ïó^æû÷Å -γ\¡((èRŽ(ª˜-Ô¢3ÀñÊjvÿ˜•Ãß%Ì󚪎´«—½<¤RÉ¢¢%Õª­bÁn66õÜâUðYmô8’,žw9‡Æx-¡PA‚ŽIeF 11˜Ã0#Q$0·$lÒRPë¨_dÍŽÔiRU5c³1;0E6N¦×+}ïr§À™æi˜ÖÖTQCÎe:c¥„Ç$ÑȲÉÓ pÚu’4ˆ8)ól¦jÊš·ªÍ¢9D´«—U<¯JxȬ,̬mæ,YˆØ.*EÓ'/ä5 lç%Î ¯ðçˆséÝg9giÔjdV¢¶H6õO„³ÌØÓµ>ayRÒ˜©jè&$j- ˆ;†ío{`zO?ÀÅE6cC%RL±FÕ´à9î<Û½Áô8 øT¾ 9¥ mKe™t…–©2‰ ³Ê·Éo=˜B€·'ro‹ít,žÞþ!›ÃY<£1‡)4p>ªI¥ ¾WQRÛ­º îiy­e=vmQO‘ÖTICXß‚ZY˜´QǼJ‹&Ú·¶Ö+‹Nf´™¤””sÏWKCdG hŽ’´šÕVK€«ÇQ–ÜX•IšdóÖÿW«¤Ž7o‰Êªç‰gtQ¤m· Y~R5U•Њßx¸RŒºƒ3É|=VÕOO˜×ºs¬j/#¦ñ¸fµ‚7Í{ì/&][ÿ¥ü7ª9ó_Ï¥ F¢#-UlÎ Y b #loåàžN3ÄVf9•=kPSÍ *LqSÀ]n ›Ùˆeó¸‚m„=jê<®¢¯;Ì!Éå•d®1Ë,“F‚˘›ªì¢ÊG“Mö°Å;ý(N»/¹ŽxjZ?ý'YM—Bâ]€©Q;!'Rmum‡ë€+3¸« RC˜¤óÎÌiÒ2ô°Ì»#4Ï¥ (. oÓÚøç¹Õ6BµB¨ªrÉÖ U3 VÁX +³¶Õ`C\_q‹Cžå¹vaIšÖÔõ©%-QQÐX™4”»–:F£¦öµ·—<2‹èÚl¿ÄUñ@‰1£Ëê<”ì5ÙÝ]ƒ$L×f[‚Úù%½Â*O ÔÑPÕTgy–_UÓ!ŒÕÔ°2  PªXl[Rع>Qfa'‹rªt†ŽZ¶Ž*x*:TµtÍÝ¢¹d, ‘AbAÔ/`0«6Îe«¤¥–®³¨ZœQGN¦HÖ@™ÚÀoͬì÷¾ÖB—E¶ŠÞuG–É%‘ikj¯†5RF]*@ä‚É}È…Ým~X|IG>OC$ô•³(4€-K­Ê3›Z›µÍ÷8eʵ“šµÏ©CD«T]eI7¿WËlD{$3”I§6ak˜ŠœÖ|Â\Êdé¨J’¦4Ž4Œ9ak—:.…õj6Ü¡*¦…‘Y=5;¥+–’Ÿ¨ñ´'yNÄ‘³ÇæÛaˆŒóÒfz±iQ¬’tË>’P¹³X 0<3©²Ù‡‡¾+¬ŒÞEHVm/S¥Èsk[HPí`oçQºák–Ï@‚‰)«B¤Põ. îB¡厢iµˆùu+Å@Gk±¾qOÔI*᦭˜BJ5E€vÛBÙlÈ ±kÜóÍ…Ôº,Ó0øšºªÊXµ#ÇK¦ äKò±A7amñA”Õ&csuši ˜U~oFTÚþbHÔv÷ûž1m¬Î_•KMšfuz´Ó:Dd‘dSp¯å•Û{ìÆÖã sª:–¤ÍòD§êòC™eeÖ E–à› ­¸¸’#¤‚(#ª­X險®† Gä騻µÊ¥È¾±rmmÉÞÉ5'bÇ„E—Åñ"=Ó '©UWR›V¬EÀ6äÚÖà âc–6MQ›RÓÕQÄ“ƒ•RI­Ò©—H•Ø3å…¸¹ûó¤K-BPÇIºVŠWTŒ=KyÉà’É'±ÂZ褪ž²½Ò8&«y„ÃxàRÁˆÊm½ímÈÃBM•SÁšé'ÊÊE4U’FÎå@hßUÜÆÖ µ î,ÄÛlI‹!×IULe«ºMJ¢K€,~8aëél1Ê2å™R$¤¥ªš»ÉÔšR °³¸C¶ÞSqØ8°ât«ÍòèáŠbbÌAFÊßÊ*X‹½³Ì] EV:…Jèk˜M$릛•šúYF÷}¸&ÖǕѪ¦¦•ÿæ‰Pº†Ù. ¬ÂÛq¶ø¶] Ú–÷;{b«5+tMfÆÈE¯¹Û°ÛG,ùmBOM;Äɰ™RŽx¶Û~÷ÀP¤öv:’|×Ê“(–ôRÓFâ13Ʊ({ w·bAïa)é"¨…dª†VªH4D†P±­†Wåw$ðpºlú«3¤H³£i S¤()®äqÆ­m{ž×Ç‘Í,´M0¬j¦E‘¤“r¢×ž÷?¾ R®D`ï“Ô¨§c$Ê4FÖÓpÆ÷=ûoïé3jªJ³4eK4a@ºé¹ç×ý/‚§›â‘i: IºV4!€$úÞÃÌFø§œE"é,×Y“e÷¶"~ŒÊ…–´´Q$“V±c+w.àzŒVZ2ídˆ¡p7 ÷ú`÷+IÒ•ô5þB@'ûÿLÈ®Ý-J¥lF­Í¾¸eÚ$I)ÙÄf)GQmu¿ly$ºÁº m•UA»{ßëlz¤(Y‹»ýoŒ{´m%ÙE†‹Á¿ =Œ2©£¦ëCð/V-¨‚º#“ÜX×O+<ÊúNeôÛµï‰aªEVµ›‚ŽTÇ'‚/÷¾4ždž™u²§uPàì¶íß„P,šÝš1(?æ#ký%˜ÃT5³Ãƒb4íµ‡ô¾"ë4b VÅäI°[m½½}qá7A;—.@µ”`ð”n›2G€nP›Ÿ¶29¤XX¬ÌT¸:\€ úû×*Hºu(mK¹$_ÀÐdfAmŠ‹›ƒ~16c™Öˆc¨¨zŽœk–_µö¹Æ`§vªë‡Q¸RlG|f!µ¿óª|¾™ÀŒHõر6þ–ÅÃþ3¬·6ðá…^6ªˆ›µÅͬü[ñ“0–Z¯‡Y‘C1 Ý­°ý±à·Š…¼R¨­¢'–Á€]$î.väãªðäô)ú f†ìI¥ÉõLjíQPlû_²BÑ#¶Ê“ŽsâÿPC”ŠÎª1”kM/~FÛñŽm™ÿÄ Ôeðj#9‚Û‘ÜñŽNŸÃòå§ÁÏŦ“šrE‹Çþ9¦_¶W)3R± ¶•6æÿlsÅÖdó¦YÓgÅ$Vó†Ûïmþ˜åUùåunmüOZ´é&Ö“Ê×"÷sŽ¢ù,¿ˆþ¦_JlÞ—óikuAµÐ“Ç?¶;484Ù#’}~§Jx¢šoÐAø Ï•~ ky„±ÌKÖáGoü|}s™Ó®jÐÔÁ#7囨|Ç?þ~æ‘VC˜g5²üB¸†= ‡¾;·†2ªì¶tZº†’šÖ!¬qƒ]“lßÊ‘—Pã4ÔY>T¯8BHr,Iûsý°ñM™µ¯ÈàéÛë·®–²´…ÉbHb¢ÖÀÜmÎÖöÄ= gS¤Æ™ÉÛcÿë~žãNƒÍ*§`úMÛŠ@E¨ª8>o2Ÿ1Øú‡ë†?ÃÈT¸Y 0¸R·¹>˜ĈÆŒ£weØýÿQ†©Pñ¶™âb%ˆQv&Ö°7ÚØQCÒº¯"Ãæ¿7ý°v)‡ Çp7âefT[‚WŸ”^û½Î$‘º–‘ŠĪÛ •¢3j@-æ;~»‘úaì„)¦‘y‚ìß1í&V €àßaþýq wGF€;¡`@.û|K$r#8yl<¤ÃÔû¹Û²•‰Bºì‡a}‡ïô@¡#U˜Éo8cl;OPÏ1GV>Pª,-ÎÂÜb‚Iåbï®ûŒDqþn²÷g÷K_cöǺõ)`¾UÈ€ ÿë „ÈQ#CÔ#vbo}½nvß×Ç£«¨ y:oa·¿½ùÄ!ˆŽñE—Wÿ‘@¸ý¿¯ÛßÂU÷.U›I¶%@<ßm†ØâŒ•ƒ¡kæß·¦62F²<ÀYȸónnEÒÛsˆC4¤£XT¾ÙØ CÛ¤FET›å-»saka‰a¨VÒ¤Ž=-‚# ¿˜fI#bq,SH©®€JX‹G•­¹¿ÚãR®J(ŽBJ³ã}¿¾5ŽƒYõ–±Qakí{÷ÄŽ½z¹òáŒï°m®Å¿¾ H•F†Dt¥ívµÎûúc$E(£-÷d½·Ûcfb¨Í&À û ¿QúãO#>‰.„(Ûò× )è"T‚lo¬Ãa®ØóA$·ÊÄßK~»ck©á ?”în#í‰'•ÄìKBº˜Ø•#Hæöç°?o| ÷ pÈ|g$hiêúE®W¬ñi2 ’A m{û_O%­¦¯ðìSU<³RL—øË$sôï¡“‚›sɰµìmóº ÊF¨ƒ]Û›ùô´ø7Äu9l‚‰¦~C V D×°>coñZçkŸlfËŠùŠ,S¾¥˜3×|6e–=B¶•1HUdK¤> 9±?Lá¼æJ*Ì¡–:U«uw–bŸ5”juieU¾ÖÛœ'Ë+œ  lÎ ª)â*£›†mÂm¸[m±Q¾7š²ŒLÙ(¡j™-ÕŠe‘%•ˆÐ²-ŽÛísŒnýGÜ×Eó3ñfš º\šƒø€Ò)s4鱺£VöFä›^üb˘g26[ü0§¨éaÓŸ ˜YAá\HÒܱ;›ã‘Q¼Ôµ2QÓ;ÔÅ3¹UIÕÌ6Öu¯¥ŽÚM°M^}˜ÉUE$U³V7…kV&ìåwÀ}®FÅI–,‰öuLŸ6’*8§§–´Ö'’ÙA&=MrƒI »ü×$é±µÉÂßx²¨ÔGSO-l™ŒàÓµ%¢/($±K€ “óÜ“kzâMâ¬öjTš<ª¢ž{=;LXª¶ÛË"ª®Æúoå¶×ßmTÏÄfZêúÏ‹ª#Š3T.§7µ®Ç`4E÷ÚÍUOâÚ®¢ ÎZJõ€Á …úŒ¾Àäv˜’y`vS"ð´rÕÇ>yQË•B-S´éÔˆ×pOÎÇrÿ(µ±¯"ùa“k’:,³+Ã=JŠÆ¦J˜’D¢Ö¢IB6 $ÛWÏóüq9¬Ôª´o£áÖë²´€y´ÆO˜žFÜ}6MWZ•äRÑe¯OI …ÙÉPMÊ*-{ØØvì0ëÃIM”æ“|TÙU|ñ[N°dkŸ. Æéå­åäïë{ŒnÁºèj”ë%5 ELÔâyT|-LND î·qó-ŠÜÜ1ôRü¼¶Ÿ2̳Šyj*@jU5 sek0Þ÷"Äyv# ³œï7Í^®–tQP]iú”³±Œ Ôò,ª@»µ´¹Ÿ Érè$Ë^7i(éjËU,ò¢O]7åþJiÙµjÓвÞÄU~%…Fº9"Ët´Q£y–G ¨+pt(·[€ íe3|¦’¡s<¾ª‘)äC™#H$ЈÎ-$—²–.8ä ñ¾š·:­ÎëÛ,ŽiJŠhe/$tà@KyZûjîØ 2Íê £ ÌêZ¦²¨VæfšgH$!¬ «ÕbÚ€à× â¤¹ÐÄfTuõ¯K•ÎÐSJˆäC,lH.ãX(Ý}ÊÛ€/o¬lʵª3ßÉðÔÔ€%\†Ñbd ü¬K½…Ã/{Z‹Oi]I.q6cI¥ø33ÇÕ»1O)ÊI¹·bO—.¢•* Q$•ÓC:CRË,®à ”·•W^‘¿ÓkíR"n‰6mO™Råõ5u™Õf™ô%SÆ,È.4¨@S©‡Æ×á=_ˆ¨+d©S”­TñEV¡ SÄä±!™ŸVýÅ…ñ¦k#×ç9‚š,Ê¢¦¾µQªZ`G)‘AÑ` `Il ±/†rì¤H”t°f•4̆Ig©t=”r£Q°mÆç½øÃÂ;cÉ[T×ÔTÑÏMU5<ƽ;B@:SS‚¾­ÍØrZûp«Ij)XSOWK §RjµG);hãkbN×Û|EIO,óÌe‚ 4ÄÜ ±< ½¸`/ňäñ|dô“tž¸ˆÖ…î†ÞÊ6ÓeÞþ¸h*V+å‚ÿ#J½Žª%I‘%%Šjß@ LרX^æöÅÊGê"g5peÂgÔg”Ç¢4¾äësÅ‹í`1­$m&iBJ xêÕb0ˬk!5l4 ›Úâö±¬ÓRg5l«Q]E¢9jkŒÊ‚62#6Ö8$X‹ ÞÄ ²ÎéCí+Ã(É+V%HA,®[ÈUP’B¥ôé·˜kH7 :‰(aj5ò@Æ%.ŒÏ»"/`§OqumÍŽKW ¹… ŠŒU†ËÞ©¡Õ î…€¾½ /·”ö6µ^¼šjqXª­'OT‰g‰â”– ª‹e;)Ü ƒk.Û©³\ŠRšqÔsLºµë£!?á;1Ûm‡cЦaÁO#Æì\ôÕAƒ€nG`pûᦒ©©«J‹D"E†7 N¬ÛM½—ïˆ³Š ØhRXbã¶¿4ª„›åÞûñ¡7È¥f™«*¤“2–iŒQ21•…”€£së¨ÚÜÚÇße´äë$’ªÈÖe•ÅHõ ßßoC‚g…³ ºzzU¥2Ós K¥RnÅI¹o5ˆ>UÄ´5Q×å±RL‘¢º³4Î¥¤•Šɸv'Û}P}]?[\ S v‘ÞBãQa°R6Ø}ùï€ãg貪Ç:F ÁT¸¸`>Æã›Û £Ë(¦¤–ª*åH¡†7cÍ+ 1;“±öõ¦ˆSÍ/QzŒ±9uYAKB݈ÿð wÃoÓwÓ#Ø´’݈·nû|Þ¶ÃH(š¥•ƒÅ¢ SÁÔ´áÉäy†Ø‚:+S‰ªÁy#U7QÁ`6#ëoÓEJÒE0¼k;³F)´…ò¹-òÿ‹›¶í‚vÊF­¦+2Ç?@Ù…ÈeÙ´ÞöææÖlHJ:3P’WÕÓi¥‹ªI"÷6Ûæ¶!¸•´¸*¡59nl7ú£ëlF8ר¬&fu’44Î[@HΡ}ÕEûü¸ûþ|¹‡S0’ÒI5™ñ¤î,;vÇȘ3:j©F„Iãç}î ñÉ·ëÑà ªZßÐI!EŒ-ÓƒŽÉ¸Æ ¦gÔ§' g_NçŸ|ÅéÝ›ËÓMeUye{bIXšÓåÔ°ìOÓûã#*:lœ{ß×cœ’ýBÛ­¯¿§ìp ¬+ 22Ç羑v¸\në ë+j» sooÓ:&F`é¦ÄãÏ;2Gi¡¬E6'îL…šiË$ #­Ùƒ-¬qí°Çša“TöÙm©KEÿA~9Æ‚&,ª¡Y]@ÛÌAù¶û_olHCtä…SùõÛI>ÖãÀF5£G$l¥‘®„r.7ûZÖÇ¥F‚ÇMÎæCó_Qú\sÈÆà-Q %Ø–6°°½ÿ®2Hã:€(l_Ðjú[Ÿ¾È`@á§•X„ÒM…ÍÎÖÆ±²Äš¯åPÚÌMÿ—õûãwˆúHWWÊ âÞܶ0þe×ÊɧI%v@G;wÀ!¤‰d¬²¨€¤­­ÏØþ˜òXÐÉ¢I\òÚ¹ý/‰’V¸$%ØÒÄîN!$¥Œ‘–mÞ×#Ù ·á>©š:Õô’-©‹æ"çÊxVýŽ.U}&vjd¯¡‘b‚HÐ+hé2 †{j7ò7àîqÉr:Êì£7¦®„J­€•¾a­xϨ#×Lн%_âTó4©øˆÃ*ÚPŽý¿AŒ¹±zt\Ëàê>††ž ‰*TjpPyV#ºß·¯±-;1˜¬--0 G@Hb¬­ªÞP6¿~EöĬ¹œUU+—eÓ§æÁ ² z¶mDm·§¦£NžmU4õðËIT5ÀC n²oÉ¿”Kw6ÆYD=Ž^Jf£ŒÖF`.Hv7ÓrúqºÜ}‡lEI=-,õ+$ZgUòÅò™.EÚãgeqº•߱䯓𢫠UD²:Êb¢’âß–À•!ƒXêø†¾¥)¯JY$qWEpÅ‹æ6ØÝ»]Τš°Õr‡™ýfYðˆËU˜`r)$y<ñ)ŠüÀŽÄ¨ã¥ÍRG ;¼ »¼~vg-©X¡>K…>ÛÇRÉ!¢ rʪˆ•À/$`€¥€Û{ƒ½‡ØaÍŘG).µcX^‚ÓÞÄlžbàZÄ@·8*\ô+å rßãÔ2M–š±VÅd¨ÎkÛ‹ ­k)àã9 [UMBez9#‰¹]ë»4wÜwcp4ê&à*²|Ó% 9s Í?[K±n˜¥Õveû~vÀùöeùë=}M­WhFtc§k*ð@ÏóX“l:{‰Ëoˆ)&JXòúêʇDoR!±F¿ Ç6æöb1YS]O«.š¦GšK¸v÷G21Ô åàØßŒU)ëè…2TTäSÒåñÎ&’4© ÌH$›¨±ÿ@Þ£$ñ]=mttš)é„zD 4Ž|ÁIb4DŸ°ô±Ib’û%«CJœãÃÑU°uU55$/ MW!‘«*n»r¢ÅM¶½Ž)2Ûç52TÔeÑ 8táiq*t¸UMˆ¾‘Þ÷ßåÌ~ »1ˆtŒr…Nª´æírQ­±+mïpžFä“eƒŠÇ•ëF²1ÔÁ-«}EN¿'öÃB; 'eÄ5ôSœ°¬JÒGG ÐÄ[f}6 ’|§rJ‘űXøè²ú4´*‰òG'̱½¸¸õ]½ñxñeFEDÍIEלÊÂ)dr¨ö±$÷‘¬ÞÀ€ Ú×5úÊ:ɪ㩞L‘C$‹$ѵÞ+{rI]…»€1ªÄ’®†Sææ9m44ÖU=Gü¼1ÖRݵìK4mÈ‘ü£“cŽ“xZlß9¡Ëà˨ž µ"éSÑÍ*GOK&£,Á¤`I:u %@ê îXÞË$¢ ¢ž¦¤SxŽ„5uT’Y"3($fÿ6›‹@º–°'f•ôiMvES[FÝfZú7Ò„bºb‰‡•5=…ì ±=í\šºhtMG:æÇ(’º³¼&®ªw“U€s!ÜÊÀ1¾Ú‰; &§šÐå­]¥óUž† zЦ§˜¼…) ÒQÙ®lÖÙ/Í‹ç„ë3iëhKIÕb›TKUXTSͰ“B¡QvbÎÛlür2ÚßGD”T ˜ÇÕGQN¥guIˆëo9NÚ›¹¹ÅOà—=™O§È%\²Á$u Q(¦èT»+ºj fb©ü¼ZçmÖà(ͲØAPµbžˆÁy¡iG—K ²ç!Aã†; ˆ3Ox¶¹èM<5±¬rD&€!.Ò@ÔÚ¯¸±Á™SÌþ+8–:,È­CT<ÕHC.›nVÖkê6ÄpæÐEw)Ÿ,¤¡ž›2Ì*©fHÞ¦B´ˆ¡B•s¤0÷ke:¼ÃË›C=,¨sˆ]ëfÉÔ§A#Ä[¨ÈÜ_ù² ½±‰jâ¢ÏEKQTºf˙гtUô†ò‘r ^ÄØo°ÂÊ<‡2Îë]åÌ㤦4rÅ$ˆeUˆ@E÷7ÞæÄß¶˜Âãl®ÆÙ[e”tU1Tä4e 1§j¦GµîŠÌß—bm°õãœMÕU§†y⨎*‡üéAnŒìLl.@Û¸#SåYÇRiêgCEÔDª¨é³,ºËXJ@±RIÕµìNeešOX2¼ÂªT|,zå,‘„k++î]´’/p[‹‚¹èÖi[¦QæXÑb“©S,Àæ² ¿bHõ¹Á³PSSW×å´Ó, ôúS4fÒé+­Šü¥I]>c¶øŽ®‚I2ÖZ4©š 7Òï3àë^×Vy œÚåy b½]EC.šºAM4ê³–w/.¯›X¹ .ªltÛO_…ðI6>¤Í©²Ü²±*"ÅA’AsÙ£[Ò{nnª¾:ªª™QZOËRßQPOŸQ?P» XGSdÔ5™‚šḋ.ÜÉ2½=(6 "‰{.Ëk\€.NëØ+,Ôd‰†–`QÊL¢ÄÛS[¿6|«âaÜeEc¡uå*e7Üoí¨+é⬊ªh£©xÛ΀·7±=ö6ýqPª˜ ã1ïÒMÌd{úv;ú)]ÐH^4Ö@ÈI<}=ðS¯¼eã4ðÞd<'Qâéž„ŠŠ÷†JaRÂhuÈÚJ€w HRv«6gWOšÃU`Z2…‹ “nms¿÷½ð]ˆ3šL¢|®ž¦igõ"6ó4½¯{]tþ˜@d’Yž6@ŒÝäbmí‰ÊØ_¥Âù¾Rs¸«$®©¤cqC±,’ 2€ Û}DKß“½Ó;‚L—À9gŠk+²ªü¿4}4ñSj„s¨¢–ʯº’ÀPu¡*ñ^f1é#H!AòßÖþþŸAƒi¤IæïNb3nX5Šê® Zýñžx#'ºÇÞ¨j3LòŒ¢Irõ’œD|ÝRÏ«UÜ\› €úaFcVDï$Lë;«*€@Ð/qk}w÷ )rì¨UNõ5/JzBTPäþb€JnH>ÄóŠõj151G#ÊuiSämÉ úY |™ƒtÜË'UIT#‹mô-ú—³TJ–TÕ‰ÔÌ. ƒ·`vÀ€Ó®·%…ŠÜ¸;ó·ëFaªxÝ(â2«,¦ÏÛÓmC¢cD›Tºõ)žæÿ\“<àD+I 7e]¯{ý°ó¼Ó ¨,×vrpÏ.häs®$ƒY60 ¬ÂÀž÷ý±˜Kš ÖGÞÏbE­¿AEÕ’ÍrÀ°¾¯”íbOn¸lÃ××LÝx™<ýd¼ŽIöíˆM-õJU p“ù¡­åÿ¶ö¸U:â‚ °¦ò¢'ó%\IúcYORXàŠb!YU˜o· ýíïƒj‚TÔÉ%4!âg¿J!W¹@n×ÿ-ûài5§BØ-Žû0ÛrGžÛá…=®uš~iDe…Ñïe Øß’Lfx~(êªÌ“,s,q e†`<‹u‰Ü®ý¬IØŒÂ9íàd>«™¤hcêH5ꈫ©M†à¶›_{Üð²™ÒÅ,zŠ®‡#ù@ ›wØ+;൧…”¼ ÊÛ.¡”s}Í¿>Ø6d¨¥&1!{nYÈ+_V·ÛØáâ¨Û.„b#Ô:nàËçM‡$X’;vÆä2ÅÔ ³Hä ×b-sÏÓúc,CXس@'Aî8¾&§!ˆ‘ãè êf½Ø‹ßoûþÜ+M4U\†ÀˆªæY„ml@:£>caü¿1ý±ô_ü8~( ±ÿ€gREò–$yMϦÝûcçÊX‚I m2ë»vWàlwÿéôÇ”uFh$t›V‚áÿ˜ ˆK~£×5zhê ¡.×Cäħ õ?@äñ]Q]ÕqL_R0kßé‹ !B}” ññ7àω+ ñJ¥uDŒl{¯{í¶>ñ/âML/2Ç:Â$±<©¶ÿ¸ÇÕh2G*ŠæÎZÂð䪳†ÿÅåm.aœÇ!XÑ–àï¿õàãær,«Ð$‡7ã“`C{rqÔÿ³6Ï3ºÊô2iÒÌ7)rÃkØqÌ"‚I&X#w’B$ü£PõúÜ}F=V pé㾎ŽEQHò’­REÉw± ÿ¶×ÅŽXÀ §F>oÜXlBE½ñ =$qSô¢†0æ0®Ë¨ïë·ÓØãk™åfak‹0×ä^äë{Øñl[9î$#êÃ#–žúb]`yŸÊY~kù»}¿¡ÄUmÈ’ 7òžMís蟩çtšE/3WÍ`.B‹?^?\l‘Ì‘ÊÌŒºN’$#WXwþ^=pD~äZžPQUnª|ÀY½Šö;ÛŒÌK!™õó2­¬xÞû0d”£.•€Û·ù¿n1¬€°³ù¥±%XÜ1ò„Ûéo§|D“€K:ÄJ,bá#Ñss½¯Ü›±DŠó–5²y‰N›‘o©¹šhB¶µ[³àðFû.çnÖ<‹œ c©žŠ&qe×eÖñ·þ˜}¨ã¢)ã#ÆÄ|¤›Áßôýð:« c:A¿Ë§†—÷ÁnŒúÞSæ6ò›lv~ã±Î¡©ÀþS¨pnm¸ØvÃ@XtE‡‘·ðÞØò$‰B¨²}߸ûà„¦§«hÝ&¬¶2G¾ ¾ß@ÁT*ÕË\"(ˆgU6%wïÿÁk‹`§î$ö%´†ÌG®!cù ©ÉF=ÏÌ6ÚÞÄßWÇDÒ£BÕ Æ6 /q…Ê:¬±3¸Ò@mmÁ?ýz`D +ut)[‡:Á'½íûã"wyZgÒJ‚à(ÞÜmö±Ä5=eX¶¢ñõL_I,E‰úbt ±¸Ñe/n,.oÏn0X¨ÆŽ.´…Q4æem€'‹ž~øÔF õ%f’RAU&à ~–Æñ(dXô¸Y7*Ãw$‘µý=±¶ÒÚ†1Ÿ7{3vàþØ$ŠhÐ+ ›]lÛnTÚßkc"Œëp—N×aaöôÀè’£kVµem¯ë·ÛI>eÙÉ\zßúbR :<²+šŠ¾¢° óïèqèhÂ+„uFþ[‚~ý¿|jB4` زßLbÄ%©#"û S*ìI{·#…fò˜ãé>×A© Ù¹õDZÀçJ°ebVþK“éínq$Q,‘¿1ŽêÌ µ†<øq,"We$!76ílB&m $Äoȹ] ‹·¥ý>ØG‘ }N Ô?_n>؆®BìvgÍqÀõö#‹ûb=(þA bAuapI{ù¸õÀ#àÞt‹JËndØ\-ì;öúXí«F‘¢@b"Í­–Ä|Ûw8BˆÕn€Ü: ^ÿ×ûœK*ÆêqFp ÷¶ãÛ×\@0Œ­ÕV csnM‰çílaY:jªêK°PïqkƒíÎübIcŒDJ0Òx'v;¶›Ûæãò€1d!,[Id%Š›°6ßùc¢}:„NѲíªäjÞÞo\nª ´%ÕX ’Æ÷¸¸µ¸ØŒFoê¼EÇOJƒÿp7¿ë(¸øs:êÅNŠ)ç«VA*°&à³pvÙÜw+èlʶªª¶ˆG-5CÌ*xŽ€_{}Šk›{ûcŸA*Fà–F‚±”]”éÛ~ãQ?ûqbËë`Îk$†PѳÆÊcÔèMÔ9Ô_ÛdÇÍX2¬Ì¤ ˜ÍY-;ÁÊÀHg'ÌÛ6QëÎUM2ô+#JyéE§²"éÜIÜ6µ¿{%™e‚:¨#Ò`fY,[f±±°ì ¯}»cPt•âXcóê†äÛdäboÜ9ÅrÇÈÎTè}M5E\²Ñfs£D‘‚èAÖMÊv²Géèq´ôÓÐR  ©-*è’X#:´•¹Üð7öôÂ:LÒ²á×à⺒A6.Mö$Øý†øomY ‘ÉIPóGjm,E–×âäò[“ÍñK„×]š¶cQÒH3•”o7–Öàñ¿8ÝÂ×I Ò|%LŠéü¾¸ô‚|Ú…ù±ß 3(êsZž¢ÒËNÒŽ¡W»+íç‘kü¤mq{zŒL…2ÒK˜Ö#ÄÄúUÕ ªýù6nÞ¸j¡qZI%}Kw%ìÛ{½¯íjª«ŒPAš³3ÃÕPícæ!A¬v'î8Ä5ÑÕAÔVͬHÚï¨-®Oòðp%LŽôጋiS¥®ÆÜ\‹’mÀäÜ Æ.‚Ûȯ²j*ù)+úˆÐDJk°R ÙEÍ­¹·µ½7,LÕ_ ø¶Ž˜¯æªt»zø–ç éé"™`h¥¥3je¶€Ê-k¾ç|I[³DV~«mÉù™-͹R/Ûå¶TØ»™”YÙZwZ8 r´š™Ñ´¸òy½õa° y¯`Íj¾)jNs ED‹tÔh$'¢ÝEÜ…Q¸;[qê.ã„“¦ØjÒ·cÐo¶’ko~O Ã ¾»,yiÅM*| GªÑʙŎÖQÃ5Žý…»’¯@¹rޝm™õè¦Ì ¦¢“á#¨'Run ºFó]w¶æÇ›ÛÕÏUÊ'Î&Z¹z‡UMÀ”Š×"«Tmæ&À¨Å/zœ%¬âŠZŽž†ÕI¤ÌIÚæÄÜs|II™åRRËSaÔ¼²H°Ô¡‘%RÁXZÎHkê¸ôßlS&ܹ-Ü\ÆmYáì±d¤ÌÍ Å,JÍ…¢0£‹)p|¥¼Ææìmsëƒè³š1—ÇÒÍK Dè&ž¢n³* Ó¬¶•CXéym¹Ç%Î3j¬Êª ªÙæž5E‡Dš­‘‚ÇJkwÛ[;§‚ó8Y6w&QX)ŒRM-2MÖ`t´v a 7’78Ž!”¬6ôQS Ö‹.L³Èšuøšjp@M@½•I \Žþ˜¨TMj€ALÐ<‚¢%Ö¬äT‹± Ö!T€r;b÷âhrœ¦ Ê*:)³kOS©Öf³iM[é-`¤M¶¸§Õµ ¥š¾®•jdÔ•b½€ãÌ;‘p c¶>Ñ[ìY2TxxUüP¬¦·‘~1RImqÓèÌîN¦XZüÚÁK6eáÃKž¥OÀõ˜¬FZQ$sF÷.@$°`[VÔA¸íŠrtÊs Hër¥Ê£¨¨a¥nµ<¨ZEn@7-ÿ˜Þ×ÂZœÆh•VÆÍ¡u)SK!gPÑ‘b¥¶]ùØ‹¥:á *ÌÒlÖÏêhë)²÷Jy+DÒʺa¹$"…ÞÖ,ã…-†Ð|OáaS>wj‘I¸…4ýFú Rumˆ±;ÖÔHµÕáÊ¢‚’ŸT(°]a„‘`ªÀصÈ·™°øÆ†E;Rå‹%4Áä©”R¦·S¤~m\켌PÓ°£×ñO–PÐQdÙvyQU Å=d•€Šdv%D!,·ØÏr ÈjµÕ©SW—ÔeÔ†))áê4eµ‹¸¿6<’þ¼à¦Êêft5Ò2jfg”F .5ØóuòÞ×½ì/…þ!ÉFWQ§4– *h”W,$˜Ü­Á}$X1MûbÜp¯B2z Á¨žŸ1­§¤J8¥ÅÌ-¬jz…o¤¶£kiî$Ê3È¿Œ:ÈjÙØS…–3¹Ô j.ÖSroasÎ*$°ë2ÈÊQ Ðý`ep§æ•?ÎäžM×J÷Å¿$ñ|Q´MH“¥q‘N“ʯ$È müÎ}Oç¾ Ó“´Ñ\Íą³Ž4ðÔ<:ä0‘b¶¢Ö7²Ÿ*‹“bM‡¦ÀÍñ´¢8¢ŸY®LBIB©Öä€/k“ó(ˆ¦¨ž]LóÊ–ºùɸÝ>öö;žqä𕘙ͩßCDªMéäÚý½0eNM A̵GBÈ–pÈG{› ù¶ m÷=ðLsUC«s ¬„B‚ÝXƧ:ºcùUX“}Á;Fb|•S÷+•JU–$ˆ²‚ )6%Ï qÇØŸQ€å…Ì¡&GêêoËwÜ0;–#qa‹ 2¼RO-DÐÔÎe:ÑžÊdSmέäÛn76'ËM=E µ¹„²Gþsh`Å¿#žÿgˆö0¶… …DoHd} f E¶¸¸ØÞþÞ¶·‚(ãŽ]113,zšá¶`/k‹{á…fY]ñtÔõPU­;Ç¢’Ñò“m@R}O8i–(¥ÖõyzÔ DŒ ƒxïæ[í}­¾ŽÐF8âiŒs:Ô¬š¶6{ŸnØǪ "…œ˜ío›ï†¦&–Ĉ,ÂéÚG›Q>»î=oBFùrËQ"I¨ƒùlêT›+wÙIúí† v'•¥•ƒÊˤznŒF®ÃûŒOO˜M;ÅPXÆë`o°67ôÿ{sƒsL©£Ðêé"¬È €"æÅ¸à¹Äô†:dŸK:Ú8õék}Å­‰º=eOâJ闥鷀ÍsÜy¹ß× kªËM)‰ÒÙ˜…mΗltÜl·ßŸ6 zx–A%Lš;#+‚,-ÍøâØöJ$H‘¡©ó>÷U”›ˆ•r@óXîY‡•íöpU%+2 ‚•pÖ¬l{oë|ÑB¹AéiYOæ5È÷ÛýßÏKPè#€âéëeqó-`}û}Æ%²Ši*$e¤R1,Â×pÎ܉Cš!%Y÷*ϤÆÖ"À‘oß¾$¨yÍ¢¦Žë"-W}‰qÀØÛNBÇ38I†£uc¸·| ¾-žÏYWÏ"Ä©U·çG0*Š múßëŒt¥f5PÌ‹Z(¥>`¶¾«Ÿób:jg¨r(éX·M¤™T]Å&ÖãÓ½ ÑÒK0¥D’tÎ&˜ ìUTïÏlð‡³Ú…1U•¨–™™–2’BHP 7;wÆ´jÎ h’GkFpº7ÜwljðÔ V*ˆú6§‰I }&ÀÇ›Ôö÷™æJùž¦§ô„²j,¤w¹¹¤âÍŠ=É G(/wç{ ÷ßúßégY¤ ïÀòDä±ÿÇW¸`ѢƬˆöPf°¿6öØ_ÿŒy•éüípNç{ý»âv%X±—B!Ræb-ç[ê^ÿca¾4`‘kpÀ¨êqèOµ€®MbÌË/È5Üm¶#ª¥xcg°6.‚àö`ŽwØ’} | I1L‚fÔÚU¤ÊEøúcËIÑ»¹r.F¥¾Û‘úÛöÁ«FòH±” aÒ_.ÚT“½÷½»àaÆD—~e A>¶±?åþž§Õ‰D3ÓT ’&œ²èò€ÃÊî,04QÓLzup­µy€ qôþø%ä°häR¤ + Øwÿ·õÄ%Ri:AÔ¡‚ØX±¹¿é‰d=†š’E•$&‰:-ÅûƒôØý°Ã&ðÖmšÔ%%faP¶ü¸ãÕ¥FÞcÀ_©ÂǪ¡DNX±ß(à ‰ÓÓ(¼I5 ¬¯Î+¾+4y+fŠ"© k ÷$÷;í&icvxáŒKm©öÿ0v’èZ4i%T¯—æ¾ßqýñ*¢êDf}LYl{‹ßèlL‘™Jît)%P§žþ¸ÖYŠþ`*¢Û‹÷oµ°´ hÒ=À¹é¨ccr·|MNt£ÛT—óo*é®Üóûch)g•¡âRÄ=͉údé6,®›ìw6"ÿÓ÷Ä!´G­JX31°"ÍÀÿgöÆäþoYjÔàqk û_õÄw s"Ã"¢;µ¸Øqôïcm7´¥ˆÒ-a¸íˆ«”y:êy ]™ÀcmJ÷ÆñˆE—,Ž-ÚüŒb„$F؈X¶÷þøÛH‘f”·•v; Ïö?¶ HòõRþbH F£¶®>ƒtÄjCÆnlRAo.åOðyÇ’²•h wZàp£Ü†þž£˜ÊUc*Äjµ&à[½»âuÀlÝ@©A¨ ‘«bEÎÿ¶4ذghPjòpHäߨâ[ 6Œ\äršNÛX‘ë§÷Ææ™ Áô—`©©ƒl~æë‰uÑ ˆh/dˆ1°¸coo¡Æt¥iGÌË}ÇóZÿoÓD«b %Û“¿úmöõÆ$0é¨V ‘d_[ –'ÔŽ0nȨ)•R¡•‰¾»‘¹··Ó6¦Uê'Q"ÆÊ>ã ‰™B‚.¼»§ïˆª:k`Ä¢þ@7Ðq郼€E$„²ž‘aa°ú{b@j)´´R$X›’t÷ýìv½±4H¥È*4‡¹ .Ü|f¡!¨'fÔ··a°½¹ý±ÜNºPfQˆáMPÊT#9 ¥ì íé{{a­;ŒÎ¦¢Z¦Y¡Eü¿*‚Å»ÚภPïikXöF$¤ªziC¶–Rì/åb?{b¬˜Ó\ ™mš¢JÚ™a¸5,Ý=í¤ ­Þû›“}÷$ß#Ö*tiÔFÏ.¸ÈstE#Ì;§¡6½ŽÂÃ%l/©J:wóÑ·oƒ_0ŠH.Ò&†É¤„àX›^þanÇnØ¥EÇ´D3¤Íª'¬ž8JXæ¨×¡,±Æ’k›‘p¡ü¤ÚØÖ¶©rµ!úæ¬çÖ»µ´kîo¿7ï…Ðf&¢®7¬†9¦Y €±ƒÀ w÷8‘‰j¢y–E>eÒT2†½Í›Žv6=ÁÙ\=IÑ­tm"<òH"ižMEQÈØ°<ÔßߘU!)0VpzƒB€U‰ìßá~§kZ2Êcé§M:šâK—u#ÊǸÙo°ï€§™± xj „ :QØF'°ãZ \[ ÌêòߌJz\iD}522 X’IÚûIàn/¶4Šf£š*ŠºX奘ÙZK5€emîv^FžÛ‹ØœÂ8fHÒT)"9`MD¦ÛèoÛ±>¸ 8”‡BHåQæVò²ìÌw¸77‹bØJ"0É¡¡\¶y–]h…DŠò177<`y'õÄõ3´´I=MUEDâtŒ@ð=(Ð]ƒ-ɰXõm{a,.Ñ–gY i¨pßQê6úàÄ5Ì ‘ÅÓù´…{Ø ˜‹í`lD´Zü#•Ög•ÿ.l”7…¥F‘Â!!@+©Å”NÄ|išeÓgµù|Ù‹Ô”… ¢]Ù†ÀµY—ƒk”튷Ä: UL‰…~!D¢òßQ=î×6Ûk {s=!Ó0ž0X,Î|׉·#æû÷YÁp±Àµ/:ÊŸF¥* ž0Aeý0±ÔL‚hÚ£Xpê]Õl¤VýìKqÎ'’¾:¦Mh¢´Ž¬¬¨·cÙ¯nûZÜïˆ+'¦ëI)‰ÌNÌÌ¥k$ßUö÷w¿¾n.ƒOÜÚ“2Ì!2;L‚D"Bó\¹ yO5ìm‰³¼ÂzÆŽf†Xú’š‰H ,ÀܨïmW»ZÀal€kK¡'KbÅ“H°¸^ËÁ>ç³€Ä1[ÌŠÄÉ"Ö¦%€i7k°bxío¨ÂÙcZÂýXÚî›ãsé½ñWl6X3zïâQÐÖ$f@Ѩ›YA{TiQåï¹íîf“*‘Œ5j GóGSPU£[ÞëΕ$íÞá{_},ѹ‘JP ݷ؃ߑƒâ–µ!ëÈ^¦0š'k[ w'`~ø.ýY@µÀ*¹ é|u'5«ž¾PŽJ»ˆÆ“Ò¶¢çd²òyµðêDë”&Ì«ÇMA$A …cH{€O<µïg’)Fª’›¨xäUE úó·®%«•¸ÍD…‰UY«¨¾›_‹Xþ»zám9¥ø–騀šàO÷ÇßQUh‹ªÔ@Ò¼1%CÊ=lŒl•ï~Ûˆ£§¤—-’a"ÀÉå•J?Ê@µýG7ÃùM(µSPÌÈUÄl­c±7î?¡À&u–¤H³fœéa%ßZì,A׸ú`mkÔcjy ÑÅq­T“‚¦›Fê-`çܶ·øqMÓŽ–ŠHWX{K3’æÄêµõÛG1Y©ž4©h£,b%obH¹µö&ø–ž µ/ÓžLÀèkÌË`yÚäò§ß{àsîuOC©,ÆIe–InV6án@RÖ°“<Ë$®ÆÀÔº>nƒßq‚©©Ýó‘Fj!ZŸ‡º)»_mþºc‹fy‘WäâIåEh*n²JÑ[M”“€FæÛÚ×¶¦“V%<°S¼ÒÏ%<އIØ ÜùNÄ.Ö<ß~0Ãóó¨=9êäc2–ëêàý÷?\ P¹ÞšV¥’@j‚`ê[( ‘Àýp ™RV’Ìm Ry¯ëmì@?lY$œB†¹ñ’§1þ0¯ùÇTö¨ w!¬@6· ŸüpmUPpCæY Æ£a}…Ǿ4–xß6¦žxHÕ‘Ìen6$“m¶'Û¹Á+:,ÁYI®2Xò졾½±DcŸ‚‚,ºŽ¿ªUêˆüµq¡t» X_žwÆcÜ»3SÔG]Z ˜¤BC7úîïÛèq˜TÆL¸J´uL3täN#gé0mJZà\_UÅÉÞ÷ÛŒ+‰ãYõNóOF¾`ÚŒK¶¦Û€6ç|ʲª,¥C,Ÿ™#Ÿ1 ëÜþ˜,­QÈ4Ç%‚¶›X6ö÷Úüý=‰“£%LK˜GÑ•‘ ºFÛµÚúmï{úúál&Â?Ëd¦V!¸;pÄžý­ÎyÖÅPz#•T¸X°¹ÜYnwîG¦TÇÒê[¬º¹òìoo½íô¶¯²¹Q´ë‰|Ò"“sµÍÿC‰ i#WH`¤y.Ã~ãoKãØeX¢" FI}7–˰ÛÖûãx‘¿åéXº•H°#¹>þ‡Óð®ÅÛ󀫥Du,H´ àzj¹¿¡î7ˆ¢D Lm §c$"Kmfòß×ùèIÆQ4^TF=PͬÊH¶à}·½½F6ÎN§†7›©#(v¾æÇHý-söÅv›àµCjì šrfrQfI¹f¶­½qÆØ,ŒŒ²!ê1ûA¿ÖàmíèN',º•å™,HK66ÿ¸ IK)d31 ÍÓr¶,ËÎý­î7Ų’K¢¸§d4¹M;–’í} ìvR­ëÁ;œniã…ÕVÔê!ˆkÞú¯oo(8:!ñhŠF‚™F XÌNÚn{Û}û`Š5¦Úzy—¦m,á®ÍªÊ¾Ö ø¯w¸|»x"øwX –[*Ø‘co[z{à)eK*Ì—V:Xƒsµ‡ë†9‹"G‘~m…ˆã›sak{b#N”ðËPáTò¨èwr÷×{{[àTÕáµ¢‡øœ’ v·}ðe&]%d¯À¬ÌÊššeU$Æ’nwôzßkb#ÖL.ŠÉ 5.ÊEÕJÞÞ‚ø*’áFh¥ó¨ \2/¹¶û‚>˜Y6 «ØY_Ô’RINDm“}@€©õ=ï~øn˜fŒ£:˜|£×éƒf޶I@Ä…©n¶$Ûocúâ#Kù±LšäÔ,’5‰”s}Æß|üP‹†E öŠU†3p©Í˜{žÇGß”ñ°K±Ö‘úîmoÞØ&4!S*«’T@3KÿÝaÆš6ŽzvR¹×±¶æÛíï†Rô 3ÚHà–eXÑpêu©ÜƒÅý š j€È½HäÒã;ÚÄúl~¸Ñ„2u"»1;‚Üq±Ø €Óÿ—×ô¡øY •ÝJ¨þm>£îwôúaei‚‘Zš¬ÂµT2‰ì —cÇ­°²?„x„Hï®Ä‹›\Ø6úé7÷ÅÛ %’]L£MÈ‘ÅÔˆ÷ÿËŠýfXùN&`Ež5 ØZÿ²‘÷²2*”E ÖX@ù-nTzïú4É"šyd™ìœ+cņÇkœH(úGR:Öüô,9äzoŒž Õ*“LîËbAãkÛßE}´ÑN&s[%1TÕ¤B[S1;{oëê=EâéL‘1ëõØÆ9&ßn;àÊ<Å)Ù™¨RP‚÷*HtßcarI·}´‘µö•ªiUª^HšN/¸äÜlpŽiz MŠè4ei»yH¹ü×¾=ZW!“MÀUµù¸ýÓ¹GuŒ—,T?婸Sß‘cÎ I¢mF²Ó¹B ¨RIVà{Ÿ·÷ƪ‡eQ5i`ì³¥'ÜéßiYt¢™XÜÁ‘wâë{ßspOºúú1„™@`ŒÛ;m·J® Ñ1ÿ¤dˆ Uô÷cßžßr1“DU)×̤—Ѱ½ïý¸Æ°™XÕë #b7Úÿâ[Ë1*®Ïaå$¬O¥þmö>÷Ä%‘è?t@Skp‡®øƒK, (Œi° [Ì­±,=ˆûà•Ò',±ü­Ó}ȧ×LŒ‘+\n5>À{ bŠXÆ)* ]ì}M±¬Û®±Ã$º”ê1.Àß]¯o¾§ # ¡ä¾¢ ÞßM¸÷çtâQDxbÊ6 võ_éÛ„$…b^Š…Rˆ°±$ïê/úâ6uhúŠ ê°T;›ì;qsýp^Ð$èÐ¥nšI#n¥­«ôÀÝ9`M1ÁP[ê!–çÛ¢z öËë:±Ó+¦TfRÿ‡ó_~pŸ0+5;´‡Ët‚¨nIÂýýpžT¨Hîuéca¨ß{ö~øö9ä§dpöÒ÷¸’/ßÔkádˆX 2’µÓ¯T)wŒ’H#›͆öàm‰(êm"Å,¥$ ª9i²ûíÜߌm–æ¹eLlõ§#‘bȧ¤TÎ÷d`w»ïÆ54oQEu‰5,V¦ä8Qcsm¬v-~äûÛwÃÙ-VÑT[Tf;)¶£cówàÿ»cÚy3ITUf`e´ªN»åÙE‡ßi–™P²ÉÈä`Èàì.òù9‚N$Ëå¤w•’˜,ƒ¦cq`U îAÛã‹A¹>ÆY­`¤éij»J® ´€ ì$¿˜ê°‚ö#§¦5=HŠ8ÉVÔ…î[ õ'aaÅñ 5’tJ¥c" nÁ…ÁÛ{¿®媳‰£­ ¥˜‰ œÆ¤ê¬–ï{sűL ¡É<ë6•ZcYÞ4ŒG ……ŠŸ±Žx£‹Èó2º†F$…bN =Eý0áéèÞ)…JFMiåÞ%`uó·Ì÷?Lj´æZi(¹™Ú2ÍI¨1-kÞàŸs‹c$Ñ*…Q/@G$ècÜùKØënû¯o\oP†zR<…Ewî‚8çìNŸ*¥‚‚Vš®Ýì ¶Òذã0¾û„á}o–v˜Åi˜Ï=ºˆ”0¥D{Ɔ»)R ØŽ  ¨ÖäóUÃYAÒ§A,14 :!ºQÉÓ¨·n9Âd¦nˆ”–Òê 1uIã`vÛoSlOI—FÊR©:  ¶-bØüÛ͇^„ v¨êÃ\±Š2T¹a(¸B¥Øîô;ŽÃudQ3L¬Í¥›w¶ãŸÿZ×ß|O2ÑÍ'VX‡Æ\kjiÃ&ûHòÛcaö¾­•+•¥š z±©Ôë"Øî¦QbwÔmnø 7Ã%„É4k†¦ å¨M-N&«/{ ì>Ç lu5Â!B¤²„†í}ÉÛù|IPñ1f0¼(Ì£C0$l}ì1 S²+ˆ#X[›±í½®mÀ}Ho32-gÃÂɨ—”*´…Ùxs¹£èVI*ãw¶‚±&­BöÁ¶S‰rùbIÄõ1E9M¼‡@gÍ¿nݰÚäÕò Reõ*¦I5¸h® •p}@'Ë·8µÐÈGK¦;À'È¥ˆ q¤n}?lGx’bõ2É !ÙZí±Ô-~ …·í‚*ž®´RшjZ6òȬËp;Ûµ¿M±í\ÂwŠ™’dR¤õwþo[anÀwÄO€uáW3. Ñ²4}X® _5¹Ý¹ã¸ÒŽÑˆ•5j%€³î/ý?|K^¿ ³A-€±€66ÔÊ5 ís÷¾¬eƒD ‰..×$z[¶„³$o˜ñÓRÌc1Iuµ¯Åîoí÷™ò¹zzyzº–%wÒ ¹¸ß‹Ü`Ln¬ð³ù‰nCì6w*:§:zzK+IíæÛ½þÇØ Úx¡y"UÒáÇSCù¸¹÷Õßûbz_„š`‰,ÓNÂà”ÞßáÀO Ž 4ÒIÿTØî[bß¶%XÐËPŒ!lIxßöÄ|ÞªvŽIây ’¦5e¦E&Öõß|z"¦f`¯RYÔ¹ºÜ±±tð,m¹¾ÀúÛÉ$°@±ƒ Zn5Æ4—]¶ö'cþÁQÏ3ռН!PÊ5(,ª{v¾ G5‹«Dt=41Fª'’Ò_Ìm7¶ïôØq…T±ÎªòÅV©J匡€g°çMö-Å­½½ñ­(­kÔÅ4¿ 0>m:˜m¤@m~†:Y£º¡_B’¥†–7%okoµÎø)×%OœÚ!%:9«zÎ’éc§óHú­y/°¶¥]ý0=DÔ‚ ujRyQ¤/u .¿k¸ÛÖÖZz–™£Ö:„‡!eèÄyoO­¯$¨’›-ššH!Ž6óçK‹÷çíÓ¤ìªðS!‚>³éÖQEØ‹ý¿\-Jîƒ+.™¦VÖK(Ø­ôéno~mí+<Ó—–;>PçQE;\Zþ¿¶Ófq;Ãu;;ÜÕôîѪŽHý·\5 Ur‡UôÕY\u9•‹PDe²°I£+ùfÀînŽp=EJUTf«GDa•]RI‰Òäù€Õ¹äñý@DzCK˜P­kÕÔVÎŽÆ:jj^šFÊÄ›•ì0 h%¡ªI\ÉJγ2ÈŽÚîH$,Ê{â.›dа(äëTˆ¥…¬¬Ÿ5……í¸$† ÚÃïä¦hç†u†’^¬e%‰$0¹+¨_›[ßü+ÈíPÔô3V©äPëc¨†7o)¹µÖÃæf93ÖHV¢¦PGYc;7–ÜI›bºL °Y+ÍD´æJ£iP©¶nXÚì²ú_Ûì–1/‡*s6¬@©êÍP¬Â@ª·U´ìnAæÃæ®:u¯cBª ¬ Á'˸n¤5ùŇøÅFO’.G%ZTAÚyuïpT €B›ßæÅ!ÓtUshã“§4V½‹‹‚Ö·˜‚vß{{qÛõZ}sÆ!“N«Aµ€úàŒÖ«âæyfE¨”ͨ”?6Öæçü'¾!FêÔè$UxÂNF›ð7‹ß@=ªÿ™ž@õ´Ku Ô·"Ý­n×¾6§¬@ÔúÌŒ‘½’vE;X›ƒµÆHH€ :¾îà×$Îà±»®¹ô#¾°lÛßן¾  Žéêªcªc$1È· e¥e½÷n-öÎ3å½%‰Á–R–!‰mm/–Ö¹ÞÌ?›lÀÛC¥f†#ZÒˆb†%—tA¤-À7µï½¯s|o, S–ÏQ81˜ÂÞÀ€Fú–8ž HŒÈ³#‚ÊB©G¹Q~<ÛÜãzªiRVI|È×g†G{Úã~;ã4¥Oƒ±MvV%bÕQÍ#L:révk­øûþž£ ³9cøÞ“¿–+7 ߸<á߉)éPuÕüåJ¶›Yˆ¯Å¿R{ ÍuK0”Ëz–Q¨ °,,¶ß76¹3˳@e2ª©C!Üêe y&ÃlLª5´“*˪ýˆ¿¹ïµÆH¡HÚ7Á´  -Üëý Á3˜ôÇ#(J@,àYG¡ßÒØFÕtóÈñ%™è¿E‘4.¥N›(mÛœkRNòTº°„]@6;_GÖÀÿî¾ šm&'r‰Ó)¥¹7û›ï)ã1 M¤$$ ØX›ð,1RøKí4L~"ž(¥˜>i`$öÜ~¸/)Wi• H*#U:¤•í±>e·66Üö ¶ïˆÌò‰d½D„.E…”@Ómü¡–À߀/lM8’¨*‡…bÓ®î.¼îý.0'º„¯¨Zs°éÃJê½÷>m³ý¬m‚Zjw£E==î}o~øÚ†–¢ª¢UŒ mj ¾÷ì ·ãc²¨ÚZµ¬šÒSÈ]R·åÇêmênwõÅ[¸ät…õ<5JL1–1ÒÉpmrû!¿¿ÔcÏ‚2æò¨: c©n6 ÷8.¦Š‚½M@WåŠ •UbFäðoca‚©]– ;Óž£Ä b;Û¶üážfרS¶AP­ §Ž=€e±R9·~N34ˆ°-JŽ£/ò¶¸íè×ûlxÄù“¬±DIWT®Yü¯kïcký°³2HYòÈ 1°[ lGk HÜ…mY>`h©¨¡•ã€U8m@vÛù­¨ò{wä„õ/T±é(Òô‚‘²ôì}?í¶7èUTQ¤xƒÚÖöS`6¡Ò¥ÅƒŽoryÚß~ø±ü#¤J% ¾¡‚4›¨?L-©Ëd1-9A³ †@[›‹7Ì¿Abùé)¦’%hc(5(©@[†¿–ý0 u ¯D’2ÔŠiu3ê“e_ê/Û²û>Í)tËHöŒvkÙl/ò–ãœC0xѧŠiZ¢m ‡™o`yòÞß©¶íÔZõeymLÙ„T‘á:ˆ‘æ:UUU™¶öPO¹ãr1.^imKMW$µ´ö #Ò^9ØÙ®w* ‰Ûp,/†QAñ}E14AãóJ)Û·›l¸ÀÓЖ<ë ü£B_kµ¯ÛôöÅždExÒä×)¥¢ËƒTÖÑGš3¨ ®CL+Zéo›kÜâJê<¹LC&‚ ³FzÂO‘I;Û¶ÂÃpÄTJAK€ €F×é°úÛÐàuVøg¦§u±$K¯žWéÍÿL#¯p:¢:|¦›«%T«~kÇ[€Hò’qãeô)U’p;én €Z÷;‘Ë£¬k!U ÙA*ÜÛUþØŒ$½(ã.¥µ+p“¸¾Ûö1»Ef†Wvy$Cy`.HÜíö½±ªSºÈ³<¤"6á·qöq,Ž`kKmO"‹vÚݯßü¾§HÕ˜–k†ÑNÄ86ãk_ßn&Ò¦fX‘\ªÔ݈'ÜöÇ‘ÉU"F¡Ì¤vmí¸ì=ã½Þi É»XXÜâI ±ª#°M¤e¹o·ëmðþ‚2)„Ecaæ Ø*‹.çö*ñ÷Æ:«x¤u íè=}q1Š@šä`‹g!ïkÿ§Û¸‡¦ò+tùC¿¦ß¦ W(‡¨(…QïæØˆÛéµ°5¢K+H¤!ì.­a±¶çü†%T’h‹ÈñHƒÊä~·ý­YÊ¡ ª$Ö“©íe½À'Ô)ÀÜFJdBýHÔHÎ!F«Þÿ]ùïˆôÇž›{”¸ó¿§m΂/‰*QP– µÉ¹âü“Å×¾5HÙB É(·å&ìuz/›·¦ס)º¤ßåF«ÜïkÿMñ¤¤1·N6gSú vû`ЏLG§:õ•­«]ìo¿n>ØWheˆ£xÑX1KêÜmˆ‚j8Vgk?ÊŽ‚æÞ˜ h–Pªoré{€»(·žq¤uEÐFe³¶ÄÞÃÜxÓ„•a#S\jÓìß-øäþØ-{‹hõàŽfœL±©Ø-ü îÞÃïŒašúŠ+ N4{vá\E>¦C®EuW:~‚ÿP9Æ© H×iKFÅ´ÚQòŽFßoÓ ³æV€  1ßIØ­þ b6PôÅì¤Ü1ß{•×ä‚4»«ÈW© ³î}ìqŽ\ TÕ}a…ï¹à`Ý^ÖêßP©;ðûZØ(°é«ì5X-ô^ä¿8ÞÈú ÝŽ¡`~»úcÇG-h¬7¹ öÛ÷õÃZö!$Ù¤1˜¢©%YV6!…ùïÀß òúÊÞH!øŠv'C.®£m߀.£Ÿ\#]z£’èT@'PîKcVŒ“Ô(–ÌTÛŸ_× Ò} tÙißáÃË|,®M[{ƒ·ò~Æ÷$QôMêR£‡ù¿[ŒRrºúŠvfK&›$„jn Çûô¸,1 zq9Wk_Éc}ãד„p®ÃßCšŠi꯮ž•V%ms<¾r¾V»à ÚÞ˜V¢j‰Zh¢s²9;j½»Ú×䟩ãÏ_¢’ø¨YnÚ’@— lO¡µ¾þ˜ÊÙ²ïƒé¥0‡O˜0%Õ;[pÊ9à66jˆš¢ž#R²#ÔÁ]õÓ»i#q§¨Äߙ՘ArËk½î¶>¤Û›amP’•RJjˆÙ‹öÙ†Á¶¯v¿ÓQISSSBª(™J }’ÎÏu瓽ïÆ«”¼´Ôe’Jk&ÓË¥)ˆ¹W'ÈIâÀ3qÚØ ,y«¦ŽIÄí1?Rú7—Êw;[n>‡|faCS ¬ÇO¼ÅR¤¨,ƒµÍù  û 0® §’sQ# á%Wòì\sÔ'°ÛôÀ·d"“á˜UÍ™GYLvàd{±}g“¿û82éY ’Ò5(p:ª.ÿÿMþø?4¡t*¥Îˆ yX[F°œ¨±'‘ë|_ÿ ÿ "ñ.O/‰Ø(ë ¨Í¡ã»;¸]¬MÅù؆ø !&¤GL¢[:­sïaßa‰ÊÐêW]vR\X¶ê9ãœ- =bé)_)Ÿ‹žÃ{b $H•µK :¬ª/åçrx=ÿ\F`"¤À!Gy>TÕ¶ûÜúï¦%ž¥Ž)§éúKÚŠÚ÷Ø`ôÈê㈠-Ôg j(-êHÆÕ“B‰ÓA1ebds)³\Ümö¶YäeE@È¡maØÿCöÆÁKëq›6žonÛ–ørA“R ¶ºŽ’m¨Évî;½±·Ä)œËTšÈJ•k77ãž?™CßKLçVíÜX}íúºÕÞ]lo¦À‡±Û‰c¡PÑÀðÁR†#¥×¨y:Æ =xoO\C%i°Š9"ÚK¤’OÖþÖÂÄ5 @"ÖØ±õ#°ÞøÜÊc‘ä@H ?šß\.ÒÜÇU™@]mf6ã›=ñ,Õ•l¯K*Å«)—@ÔóÞã·azªÖj&K_K3Ü“a¾ ‰åã¥ÿ$¨ÆìÂöíïoÓ D|¹©DrÕB`F Ë"E‡Øz¾Šª¤üTŽÅ„ #1[GÚÞÛãzÆ«§Š3-.‘fFàêAo(7úiBÐôŠI$…ÛËÓk*¯¹Ÿ\(G5SQ4uIu†WeE»ÞãÍöôöÄÕsÒÁ$¦j)*åK™%²X·–ÇÖå¶;ï…QGªe]X]Ú€ï¶à¥ýq¾O]HÓÇOP%žž6gü­1Ô)6àn/}°ª<ö({ÔÍE_åIœ´}F3ÂÍÍüÊ_ç•/VñSÓeòQŽ€„“SH@Ý…ÍÉ6¿kcJ å2ÇKIW,Ö –ÒÒ|Á¼Äl¡¿ßôe`ô¯1M ÉNC+ Øj'cÁ^G8}¨„YElqL®òc§* œc³^ü›×çfõÔµýWn¨‘I]´”Q`ÀmqÎÇ ³>­)j@÷’.ÊÃp.÷öÿëÁds,R¤“2» ¬íq~8ÛoL݄ʊ”4©NQiÍõ5¸>¼_õÀsÎ`ŽÉÐ-PX°`u§)ísý1MgŠ.¦¤ÞãkLCw,²"–’Åœ…Õaöãkaˆ0ª®+S8Š>¯QI`[V¢T©$ò67ã¶÷ÚÃËPÓG¥™‚X’ÚImkz}þøö ÒF¨ #–f,6kqcˆÅ³)o—Uƒ}ÎÞ¸›ˆ05†”F©U"<Íi4*{€,M·ñ˜¨³ë’xTB£Jok~üf'cYܪu2CÚHGAÂêoüÀŸR7÷Á5©ˆÔ,©R#@ F£P<ðyR7Û×IAÓ¢\¼»»ë`€ ÎÖ*O¥Î¯­½SÉQ—ÕÒÒÓF"p,Òò*m$ž9Úøç9¦v)Šsú_Œ– \o ¢âø¥U+¤Ë$W1µ”Ü ìO§®ÿ¦:¦sJ‚Ñ´]Hʺƒ%F«ð/{‹cšç¬”Õ’ …µ-©®TØmúß1dÝ*ËVÏÓŽV_)!”\0â÷ÁÚäš yIµ²’v݉ûq…ýEY5#1[`¦÷¹íµÿ\dˆ #ÚØîMõ ïǾ8*‰%6•‹^¿Íp&w/cµ»_s¤î6údëÌ‘¤f8d>cky"×úßaQ#4l€T3 Qü€Ò} ýqlË’2áË— ¨2éÔµ…½ï„kŽ{ Ÿ&ñÓ2G G$®4‰[Ì¥‰S_*›S|7ÑU”=n¹R€éîFþûÞØÆ5µF«'LF<¢÷½ôí{_UïÎ2fІHDò?Q´³o¨E”nEùÛ¹7Ãe´2£Ÿ¥F¯ŽY&³ ¹P¶þœ‚¿÷zâH §¦eé®gò²0"ûí€GF•B«½ +b8íc¿úãieN³º¼pCo°UÜ~/¹ý1ž|ôYÒ31øye–Fò€ªT‹) {‰½ùÀÕiO0E„ÀÚ$ÔKƒpÅu[mýwâø/.@ìÒ2LŸ–¥¬I°c·k~˜¾&†J‡”i ×ÿ ì=Îäý¾É.…öšxä ÅŽ°î_€Ö¸·©Æ³ÒM"K1_3&ÒKÛrl>˜"h* EM!Ya±½boïo×Þy#JX"ê2“v帻ÎáKcTR3N$ôŽÓäÆSå$1ÕavþS·ÐŸÔc*ý%$´­ZÃÌBíô䟶 ê¾ ãCvH@Eì ±â~ØÒ jk¬„++\aåÅñª„óÌi I]‹/°­éî7Á}TªLŽ%Nv:Å”ÿ‹ÛÔKK«NcT db<ÇîvØ“þÁÀâ2ÆÐ u  »ök¹SìVÚvš©c#ª s®/ñF¥‰ ÿãc‚i–7w˜ªõ$µ ȶé¸î}9ÄqÁ<õ*êl¡Ölußo顈Ñu‚™Ø èŠ0¢8$žçôÄ—È‘o¶ e¦Õ:ˆmæ7ó/¾‘RH´ ©ÃJ$þk þ‚ß¾1,$$êˆB÷aeV‡{’ Ÿ|CHô´Ð´óFòèÓ*F¿-…­ìpbùd`3Äf}N:@ Ø\ê$ÜA÷ĤO*KžR¢'ÖJ¬(.vê,öï醰Mø˜#[!%•¶^ÀqÛM"A Œ˜¥”’ÇO5®;žGÿCò ¾À$TJé+ç,ÑtEÑÊÆþNnl;‚;óµ×˦)ºÓG „é½´ÊŽäßnÀœ<©WÐÅÙÚ?9ѱñ· kîq KR©2SG‰Œ;“`7¸Ûb8¿®- (¡E s*ÔõšÌŽ e³ ¾÷¿ ~Ûà•¦°è#€H,Â÷7?^þ¾—é)éÚ+UäÒ¥Z@H[’6#¾Øõâ•©¦ž•8ŽÌ,ÈÄ6§’.7"ãuÃn¾Û]Ö‰>V6Ôöd;[O¾ý÷çÛªtçø‡Bì5tÿ3d¾ü}IÃ`‹;ENçTm2¶£Ù-k1o×ÄÓF ƨ†:A½Àµ¯Ê­ýÁÁ‹\€_T´ë$p˜•š]@]šÄÜé–¸í‰ú¢Öœi†›…"‘{þ¿û8‘ªT†©@it¶)uùyÚý°¦…ÌDoùj¬·µ€-«G©[ÜÿŠÜß ¤) M<…²9¼Ê4üÆö{qˆ)àR¥‹TßÌw¸ßéƒJ=B¼Ñ¶²-äò‚/anÜŽ}1¬mE¨*Âê]¬oÁ7#ÐbÕ&ø`«#ŽOl4Jî¥5·äq~ ñÉ¢Õ*¥‘nB™/½îí¿}ñ<+®&–Vm°‹/•G;Î5‘UØu騲€v°ü`ÂWÀ)¼rèD‰Òçž.ÓÇI$Q„,Ê.K‚IÞݽ±³Æ^D!cÒ6Ò¦Äýñšî"S¬l Zëk’9úâ¶Ú ñ´^[Ɖ©“ʼ]†ÿ¥ÿO¦#0¬9j>¬rDãK*I?Í«ÓÉ ¬bYaò€[Ø›ò@÷·éˆ£…›™YD‘;ƒÓ-°ÛEýÿk`§} â=òW4• 25@Ö¤­ú— ]IØnÂÿ| <0*m;"”hÉ>cíký0ÚjYä.ð‚Üý€;zàg‰žušÔ\éX¸ØZçŸ^0Ñ®-PÓ™Ay¨ãy™º…Úm ‹n½ïÎ!ZqÔdhº¥‡WV ÅIºé¸ôçí†pFåZ8*ƒ-¢TÛHï`H¿ÿxÑhãpœµËK` ªn{ß®MvÀ¢˜–¥ Ô#¨:ôj³®’~çœIQcEIœÄŠ\­î¢ûØ’mÆü`Éé^U§œFÚ:…´°k›`»o¾ê²I²Y•\i%y'}öÕkzínów±(ŠM),›2†b£IQ·¥¿¦4qxÚtê*k"2G6¿›üÆþØ)„ò!TP#A¹[y¯½ÿ|cïä,¨äiq¢á¸ÜØ]Þà}K r5,ÀØDzž×Ämf’>¤ÆûŽ¿Ðâi”ºÏ£¦0l[ŸN'h¢D_:¶¿œÿ5ý¯ôýðl ŤI"^™žKqN1¸˜´’˜®üžÞûóëƒ'P2DÅ® lœ óˆ&u çÍ%×ry$mˆB2ìÈEÀ l·\ß}ÿ|z[S¥Rû‚ ã#) Ì ØonØñLLƒþ¾ãJm‡qúßÈ*GEÒBŠƒÊ¦¦×ûýðÇ*ÊàR¡aK•ÄŽI·ûì;œ!‘uÈËsäžm¿ö¶ Ëjj²ê”©§ ®¶`ob¿¨í>cHƒœÌe’Â>‚Tô†ì©Ï×¹ÀðÎñF¥)cŒ¬ƒf#¹ôõÄO™Šº‚õÆ Ô#îÿkTÈð“G] åP¤]‰VßÔX°·¿½Â¤Òä!R|n]O54tñÌ#tgiRiyGb©Ô~€wÃDÎr8i§—-ge×Úô¾–¹ Ã}ˆ ¶Âö786:$]$ñéø™©ÂVuhÜhÒmµöïr×À>$Ë)…j©ž¡uÍ¡#¨±c‰7à–'ô'Œ-¦è6ffô”ùU5tåLÁ ˆÀk–²ª‹›ÀßÓQŸ(4¦¦SeôQSvÞêŠY‰6ܱ$ûœ|k“Ñÿñ>O–¬‹ Tf4ð I¸GyoÆNØûÞ®:*ïg1IW54ë1Pj6½ï÷þ˜0$ï£&Š~¤= Rü=U1:”­‡”ù¶-fß‘úcæÇÏÃi¼›¥vPìþÍßVXÆÄ@Ä1=Íü Ïb=>é%¡ž†mLen™üÀņ Xñ{ó¾(^+ðNWâ_ f~ÎÞU‚±„™|Ϲ¦˜da}ü»þ Är-ŒÊn64Õ£àú8$¯ÙÂ>Ì¡ü»wo\FâšHUä3È¡*‹÷ãúœâÌ’¿Ã9ÝfU›SÉO™QÊbž?Ìz©ƒèFK ‚Í5ÑØê¹ÚöÓnØÚ¹äÊ$(.lH{]@¹‹þ–À3Ô¶£«Qaù„†7'å±cÎÂøÒÚÃÕ¬5¬Ž"•B®w&ö,?L@†Ñ$zãJ©ÈŒYžÑõ4\üݵlGÛOYNáb@Ê¡æÚœ°Üp;€hELr‰)ÉY€/¢ÚƒCéƒÒ¦ƒáì)䊦2«yIãn÷Ø6 ½ƒ%Y TêÝK¡í}€Üò88ˆ´rO+Gc+±"K6~Æø"•?åËËDLfèŽÒ• Ã[ž!t$´NC›j°,GaúÛ°ƒÆ’M.‹†,l»…ïo[`ºHÆ…u$X“¨›ßµ¿®š) Èu±/²Ü¸ãé¸ý7ã ¼)g+Ï)r,™ ²ÌÊQ´‘¥ÂõXÿ†öQlJ®Â£¸†–’júºz*Zijj¥`© LK›È°µ‡|\Û𺲇©>™Ç š©ápΤî¶;/‡üIà\¾J?忝0UÕS›Têëàª\Ø <kØð¿Ät5&”Í2¤ÚÐ\,BÅï»avýN(ž[á å$pådyÁ/"N¡¢vÛºúab¶‘ƒæoûØÿL_ápÙÎôóYM…Ê·§kóŠU4ÐÆÎH…£bŽNâÿ¨ÃÂ[£É[ᑳÀ£H†&>U 0±}žø§–q,€ª^mïÏÞØaX2é˦+iµ½°¼IJÌCê Õ—’} Ã"Ë4sI$òkHÎÀØ’Ãm÷?\fº X€-tó€Aõ8ÑäÕ)–ÃIVáÆJÌ#GéÇPó8¶ÆØˆ&É< D®ê˜•1'Ÿé¾$¥©HÒ´EÏo>–ˆ'o^ªUCÀ\äøð›È Èêû®ìFÛXÚÞíƒD¾f‰˜àS#”n«k;zßÁпœï%ÿ,…ù˜­­qÁà ­}ÉŽ™¥Œ‰æXÑWbÇæ¶<§1ÓÕ(Vt ë‚@$÷°Û…“0I2ÜÎE¦«zªY!Y¡FÆ"6Õþ`IÝN-4%MRMMˆ¡:šRmpôþ˜ ‘éuÔJ‘§N×½¯~.qµZÃH·‘ºÖÜ$rís½Ïqkâj' ~£³ ‚Ÿ(÷íúcÈÖ­ iÚéƒÎÇbVæà[è0»âµºX[q½Í»ï¾9˜7T<‘Á6Á :ÏÕ$+3ì,®,H·¯$³‚ Ø1¸µýùÜ~øeHj½×ü¾˜òZ‰<¥• cåxÚÖĤÂ4Y1©„r„º£yH±¹°ôÔLfõ)LCÍ0™mm†“þÆ3‰´úÿ:©¢‚ŠI¡£›T1>°jv"þe>›{_ºˆÚ¬ÔìÉ)‰ ¢uØñÈï°íßšª|äæi$`UAL]OšÄqs¶£…ut9vdº'†ºž`dŽg±$r‡¸·õÇ'ÏR_ ÞÚãÃTÆV…z½F»Ü³ãÓµöñ¾9ß©à3ëÆêìñ€Y¸ ï{úñŽŠÕ:³ ºÎ T©>c¿]¶öõÅ#Çñ¡†y#E‰ÙCb:…íèAûcFšu:+Ê“…•I:H5G ^¢Ôó[{\lGc¤©2%ãT l¡H·¾<™‹U#O>²N÷ßsÛœC4©b¨Š.[ñn÷õßcŸ)qHò®XaEÒ̬nÄÞëklEíc±õÅï*­1è}³¨b lvßý~¸çZT†C°o¾×íÉÅÇÃS òØôÛòY},o{ž9®„Ú-Õ’SeZã’+Ë (:¾FÔ4>ýÀ¾#ãL¾*4åMÓ[mnn}NøÒYTÆÌ‹"JC+ p·:® í)ÝN^éš3-¢«Û~w8ɱ3eŒ2õz‡E $Íæ w¿ôôÁ2–¬¨ø§&çdM%¹#õ'œ.ÊêÔ#Ø)gÃìWb ú‚l—%;æ “Ù$yåÒlú¬A<Ÿ0Æ9´"ÖîzñR¬òˆ§n“lP'ó”\ý½°š¬;¹†Mzƒ‰dB¿ªÜméú{Œ6š“Me‰‘îA[ l?òíé…³ÀK«EÔP²•I»9$nø@½þƒ‰ÓË€iª©”hªJmC«¤³36¸ÚÖßõÄô4U-˜*$.B™C|Ä×ÐòŸ¦!b²SBÅQÔ:‡LvÓs«mË÷öÄÐS;ÒÉ—T¸F’™F N« °µ¯a¿®57ÁWmÑ+¦sfbªºO ÚÇÛÓÛÕÒ¡¦Ó dt’Ä ÎHóaoÛÜa¬u0e´¦Me•…­®ž§×±ÀYÝLlÑS$ #2%Ž‹ù¸ç·ëŒñRÜ;v©€F’ÐQ6¸ÒI–'HC¿&×ÜÓÒø‚[AK!!B Žçÿ“‚'–T†!Õ…üò!±ù{q}Á#Ñë0¤½da¥‡Æû/oÿ[6•.¸cŽER½£Ý͇@FÞ„ãzpÌ©³€åJ;n-ó_î £Ž3 ?Ä$9qvéùÕn~À·ÇŠñ‡5-ü„DNîn,@ï}\à[D¦dôái®±,FÄ‚ÝM´ûï‚ §²:¢…_ÏæÝ®6&ûã׉XG!s#³ †Aåc¸ïÚÿ¾1áYÞß$LÅ.o`6Û›÷í|#ú„raš«%S… ©ÒŠ×þí±æ`ä;ë$/•\ÜYï`NÂ÷#V:ÅNŒÄ€ ¹;Û{Xzý±¬sR¥”6®€«I{¡Ûbpª\ƒj¬u±Vv4Ѽeâm±@,X½‰ÞÇŸKãiaT´°½ArÒÕ ¤mÏéƒd„‘¦ÍÉzc‹¦Y~nVÃ`–àóô¾ø„išD»Êe,ÝÎÅù@®W2SÃ3Ž¢K-ÀRÑùc M˜žÛÄI`𳨹`@¹Þݾo鉡“D¿´ÃK©Pã¹¹7ŸÛ¦†n¬ˆ„;³™@¿ûZØ—èVÍ¥B¬(E€UŽG¹Õå7!oÀýð2TÕ"$*u¶ãÐw7¹'ÔàÚ‘O%AiÕä-«ª‹.Üz_:ÌõD“1Ò­hìÀM®O?oMñ#ÏsTxRœKÆ  ¨!áK-–絬1¨ŽP]m Áb|šz –°ÿnq,$U‚]ärħRÚY¬Tû[|nYúL‘ɪH“Jùl8ÿ(&öçl5T„—"ÍAÔŽ°Rö¾ä¯°[Þøš(¡ Z#2‚¬ Pš½ˆ¿n>Ø™Ä-NêeWa/Qa”n{Z÷ích: ª’êW¨Œ§½ûÈCÊ< ÑUB™)]‰"û’Û›|{Fk* 3‹Èѳ<¦ÚWJ’½v¶,kÐ$ˆ„/”ذÛkóßÓ¾!žL%áv/Ó`#W;ƒcÁþز3‰T“¡IW‘ÂõDN¦7ŽÖP›’>ø™?‰j’F ò þUôåõÁ44²ˆ®È¨’¾St"æàöí*žÕÒj¡n|Ì×=¹Ü1?é½Ë”_T¶ c¢HÙš4ÔMÙÅÃ1Øiú\[,lQµ&³‹þeÎÇŽ= l2–jj ‹™$Ò‚†ÓpW’Hà_°%P“ g‘^á;¶÷ñß-Ñ/ƒH¹ÐÓ0`,n¤AÀâàŸSˆ ¥.Vm¶½ÔTÚúO¡Ú×=؉¡#„•omŸßùq«2ÌåK+¨xíäÄÜÛŽ-ÉÄ‹c`Ú¦ñH±”o9QaÈ6 ûàj÷ eEb/§ÞØ8«µ4DÈIPB²¢ÙU”sÏ|. VÕ[<¦ÊQ!‰¶ã·Íûa£Ý‚ìÁÃ(cÜ·cqޱ”ôƽî n¾ b‹ R¦ÛM‹_ssß|F!yY„Y‰_Ð\þØ}ÉúŒ;´qÙ×EÊíê6ß¿>ø†4]ÅÓü#×Ð «H²i ¢B€uoúcÆDí`~R“µÛÞëè~¸–ˆ 'OFÃ’uzƒnþœcÈ]ÑiÔÌ¡<©Á)NÌ@„É»±øïÆÿ\F!—[´eRÒà“{okß¾M’ìJ3(fUqÿPßµ¸àséï†Pg5‚œÓ­Hu,hEú@H´ßÿ,+굕EüªÖùO¿ÞÇí"ª‘h˜&üî6¾±†Yb½T05\Ôè*K’Üp|YøÜoñIXCX™´³l,»¹,»_nm|Qd,%U•7Ø€JñúÿloO$ÔìÎ¥C¤cc¶ØWv…{%^]˜ŒÈËÔ¨¢¨I˜Ñõ=¯»oíÐj‰éeñdù…=9ªŠ²8ª!ÐÅIGPÊN×Ü~xõàu-$D)[1Wòî Ÿïÿ»rþfYnqøyà<Ï4j‹Tä«J$Ý©\ÀÆã×H?|F›F½+Ig/¬¤šœ(¦JYA:cYC7äœ%ñ®^eUn´ÐÔ  æÅC}ý¿þì<¢¯ðå2ô²µ§27äs…^!¯x”‰ÕYOÌ·¹ Þß Æ-CQ]š±E¾ÑÄ¿â_ðÒx£Åùu0odp—™cæ²™>aîÊ#ØŽ#‚z†¸‚¥Ì‹å!Im¿}ñú)I]ðu)TŽdP‰¡‘ÅX€nob-pG¡ùßñOÃ4~ñÎeA”ÐGQ_j¬¶¤DYc¹á7âÄ5½­ƒƒ;ÛL§>š§hùâ«,ÌèÓþj†@\(Ò#¶—"ö>äo÷ÀÒÆèª²ÄÑù*ɽÀàŸ¶>‘¡Ëˆ2ÁDñ„I ‚V¨]g`è@·ø}0ü/IS•ÖR|1Ôd %Ì¢ ç¨R—)ੱ{ݯÉÉT´í3…š ØÙÜSH ê'•&ܯ©û`¹„K—(ø~œ„êeh‰ {ý~øì™žZ¹Öað¹U+=5l:EB²ê¾•¸kŸ+‚¡¶äzß eË(¦Î$ÌáWl’*E‚ªiPØÈAb¿]W?ýa÷Z±|‹áš xÝX²®£f Ûê;}±¬JU:]wbŽÎ ¨!¶æÞ c²Rø@PåKW5#=lJ*«¯ÊK7î>Þ˜OQáxs¿Sxw) ‹ãêYDr6«-·f&Ü-ûöÛ’0!•7Bù pVÿ¼œþ gÿÂòvP#@õuS 1SE}™Éî|À/rlqô÷ƒ¼1‘ø3,Oøf#VÒ’s,Ô°ŒÌul6Ü\mÓ]€÷$ƒ<%•dŸ‡™xo&gel®EÞ¦F¸2ú›[ʧƒsÉÅ£!¡Z–g–€TB )#Fl—Øék^oŠ2e“t1ŵrV3꬯$¡´t“™¾i Hf¶âýÀàöõÇ9ña&eDÏUdºN•ŠHÅ•¯n¶:â6{G qÐÓÔÃN¯d` ²’<»·+ÅÁôõÇ<¡××PE]Ç.³×º(Ö«sÉ Îþ\D• Úmœ»ñÖN¶w”åÄT™x©6"Gb÷>›ŽxèeƒYR±6]Öÿ× üeœ¶sâ¬Ó0Tu•‰l¶6ôßlÕ¥,oV+}¶oqQIY¢Ó³Ç  [¹?lG1,ÒÏn¶ºýôà„–™æUêu]¼Ö$ÚÇÛ;åÑÃ*üDˆ †˜ÆÎAÿ¸Û9-ÓZagqù€¯<_œFÒ̳d%•tÜò-¶ØŽz¤c­@yQnFÞ½ÿ®¢©ãèÍQ1#k‹‘õÀŸ¡ÕWsP‘ ¢³’lwío|{*Ñ t’Àé·õ¾5–¦’ÊDIn@fÜi¾ãË(!\Xب€¬3Ì (8äÒlR÷ûìqÕÎÒiR‘±ò‹­ùâØ†‚ -ƒCØcÙKÞúÉý0Ã9’Rt¼¯Ü’}½1>–ÎX‚é-vFï`T‘¨cÅtª+8ÿþ˜„<”ÔÌFöÉ4€I››ã^ ‹c¾øÈmÔólÄ!ééèPÒï¨ÝHÚÖ¸ýñ´ª€¯æ,‘ØËp"äXï±6ûc-“bª@äŽq¬~C¨ÚÇ"øƒ=ƒl×÷Æci]cpx'cŒÄ!÷°È­xÉ&3å^ÖÛ]^ºâ ^âFm•U|¶ù½qm©¨ÕGU0Š61ÒUÛÌEúoŠÄ5 Cá8²ÚØf`òZµîlÏpwïlptñŒ“Hïæ“N„é®YŒLLWQ ›0PT“k±Üo¿6ß3œú<Œ(Œè[ÈÜÛ_ôoᚆ†¼R3¨Z€ve ¤Ž7çqqÇ|(†Äi"ɦÉm­ìqäM"L’êU1ðH$ƒ÷Ä—ÙéS!¬ªhä˧Òé+‰¥»}Á±ïƒ¨(ÙÐt9 ÂV]lUšß·ëŠ–OY=}QÄÂv$0mWµî=-ÀÅÊ þ"•LÑ‹º,~aÏ=ûc ‹³d%jÄ”ÒFiŒÁç˜;_ó,JÙÆÛóߌ:£©Š¥¢¨t†s œmrT›  ÂEéÐæbš-Z˜§Êu{z‹ÚÞØeJÍ ¡KêX”ÒÚCXOûzß玹.Œ•ÐÖª²«¨ÑD[£©äßPC§÷8’¾&V¾…ôÉ-æõmǶ=‚½Œ­7E›ªF§’Û)'ûpd OTæI]!¼Ì¢äšÂÝïµøÂ)méjnk¾.¦‘Qz*J”MÐ\¶þçnp]1ádª©~”3fÔ ·ÿ8ŠZšk¤´ë>§/"°»)~p-|6¢•3Xô˜™`{‡ŽeXÜA±6ï«ÊW`qqÊ)+Ÿ©+S®Úv±Û{÷6¿¶4¦FRÒRÑùzÆí¨°¾ŽO°ÃAIy|ÔêÝ)R1bÖ·nucb±2Æ”¬ë¤ª+•°"ö·§ò±ÅË!L¢Û±-\'Hibc¡F†K­…½{â ã¨y — ­Ô°>âÜá”’Jõ²yŒÃmÿq©¡Š“0^ˆ2ë»Ë#–ßýì0ÎN»$Õt) ¨„ Þx‘Ø î-pïk[ 䤡 *,ó'#vQkñ}6ûàºøfzˆBÏ$á•ouÞøÐÒ¸Žë°ÁV+°¸ÒM¯ìKý°Ñ•rÀie€C¢£Ô‡L†÷'qÖÄà†¨òJE2S†;Zàñ`ïìqÁü†¡DrHÖEÒN†6€/Üoƒ¢.ñ…š5-¤°%®‹æ¿ÓÒøIIv@jwd”´Éx×{ 7·ùÇ…å&šË§•˜)º9µˆ=ü–\ÔÒ*!i£‘©–1e c°ÔxØŸÓ åIþ&eY˜I02 {Aeßô8‘VF_:ºü?LDWL­¥(5V#Ü‹ýp®^5YŸDeÔ³é=OÆÉC y„r±c’9`ÖÖßro`¦§XZ¢z™¢éTR W#ÜvàiL¡öyK ´ÒÇR°ÉMhÕÑ®÷Ò ¶°ÚçßÉ2E¦h쑨ëÀsÚÞ÷Ç„SÆ“,z§(TF/Í®~§¿éôÀðG,’H–"EóTkrwÚÇ¢TÙà "É«£Sp5^Ö6ÜqÛÎΙ’ƒÓ V46 ß·½¹ÀÉ2Ï0U]ºŒcÒ[ky·· âxÕʤìUm¦ú|º—»sDZôÄ¢vm+†Ðñ%Ü2y´Ö6$v툥ŠÑÝ›¥;!PÅ—{ìoƒ©ázºyj啡׿•ÔîFžOÌ@·¯±ÀÆ5DX$Ów¼jö\“ªÆöÛHãÓí m ¦úAEÆ`Mîn}»â6d˜²—å¾Ì ]»bt½4E¥]1MvÒÃå,;lÖUI"‰µ¹VB#ÜE”÷ÿLYBöITÔ¬ìðF±Ä5–-¿'Ün?|dÏJ²$£N€.mÏ\m*Ýpˆ”¨ê $Ç›~‡¬" ¢%c  1u%‰¿C Ä”´Þ:1tIÝœ‰.8°þÃENÑÍ鵑H°àébFûo¾ $Ef ²»æ%7bÚ±>¶ÄÔ‘¿^Yå‹K[m`qïÌ¢$Búø·o÷lB²Ù|ÊA½Ž6D™N £Æ RUGËb.{cÆ% ÂíˆCÖ Ë¢1pH¶Øœf6EDPbSP,¿OþÆ3 ‚}ËPÊi¤ª%¸Yáe7€Û}GéŠGˆª©¥FˆÆ"f{Ý›Ê@]ÍûvÅ×>Ì£93T:±™lŒ±µ®MÎ÷çp9!¨“2ÏNÂ*,¬SO—X ŽÿËn1ÃŽ/ŠãÂ;ûª7 ʼØ'‡é€«»Nöê2ùIçoéŽMã ó]šºÈUŽ­ kßb>–·é‹ö{YEIOQ=02Å‘iL“]U,ío˜VôÇ.©‘¦žZ¹eMbúCK)ÞÛ{zãv—lŪ*{ßgg±óHßßé¶=m˜þeä>[ CÓo¯íœ°Û:)Uæ÷=¹`1©PAU+¦úî;ýÿÓLHÕÈqk1bl6°¿§öÇ‹¥ÒÅ4Hæ÷U±úÛí«.·˜•[NÚ¯ïp®úK-¯n;ýÀÁ3!«u¨ª ¬Æ÷TÔ‘±¹˜»PO,FX#JãÌ¡n•+ÎÛñ°õÇ>:cŽ5ó1+¤ ‹ïõÅ—ÃŽÒÑ2<ý˜e $ÝÅîmïþƒäYŽtèX“Â"ŠWY’ULQ…6&ûúžø`”a|)E™u–ye‹]‹ŸNö-ú*̦©ªËºô€$¦UYÕ”‚<àƒ÷g5rŸÃõèÌÒ鮎Ab•¾caØyÿ»öîEû¾ ðóÇõ¦uC©š0£€O¶åÆÈYQåuÈ»°ãHÛ’*ùMJKI$ !YáŸ}¶©ÃQK#ÊÄ*ľ]!¶,Xßµ›ôÆYÆE÷NÐʦ–(ª‹|S°S}m¶£¾ûýoV ´ðË+;ÉÖéV½‚²›mí|m@B¬@3,‡¬ êÇqíƒZО©eÔI&ö¸ýÇê8ÏrÆÍ41§§Š:uHWb‹?UlNîm`0s¡ Š}“SÀL€):´–6·*IãÅ—QOXé[UÈ!þRx7ßÒøÒ MfH=4@¤(Ûa¾Ö±¿×&ªÌûO%G$5(Í%”F¬N*6çkñë€ÙfDfn€¼ ¤}íaå¹ôãí†HZ¾Œt‚EF©G;qaÀ÷çÂ"ò™"E ¬AP ŽûoÏë‹Ô.ve”»T²Ž’ùžäÝ-ÆžÛs÷ÄóF²ÖÁ;Dz±{kkµ†ä €}ðâèª:­G7-Œ§¦‚'‚d›TkæÜ’Ûwã)¤Tñ±L±BõȲ´Z"2µ‰ )²ý±!ª¥øZg]N‡bl/¹í°o×NáÝÂZYU¶E¸`F×¾ë°À-I4É(VŒÉ´fINÈ*û(<úâ,‘o‘öpG^ô²ËQ=#ÆæRB#`{1û`¨%šé¥’âB…ä°­~ÒâÜoƒça¡Š©­‰,J’mÛˆR©RšHÐÇbMa¬Ä ìGnpÏ%>«ì«*Ìa’)|ËäWsr¢þ`04%V?Ëäs((¤gõ7ß… n0÷4£(©-T…¤ @º Ž=öÀ}Dø˜F¢J‡s¨’t›_·ÔãJ’hË’űÄCK$ª&¶•o!Œ› ¯Ð®% 4´Ì¡Ë&¥Ö¤…co°Äšá0F&*±((ÁMü¤ó븶!:Cø ÐÑLDr™™Ëé…+FZà…úiÛïë,а§4ò™6C¥\./ÚÖ;zà° #F‡ëµõØ^ñS ºK!h˜M«üÝ·ÚÆÜío\2©2,²€¨Ïghº‚NËqÛq¶#¤52S¤tÑ"#ÙP¢’Cìà‘qpkb'} Á&šC"…ÌV#Ì¡ísέ½~Ø‚9©jgN”ˆ^ûÀÜÜqkzàÚñÈmy‘#éÛM´ì{ý°¾SO,õ&¦o;€Ê,«ÚÖ6ýpÔŸ]ÔoYH…Q+®RÅÌHx¹°±Øl?lC$LGVe$`«‘Àã“¿¦$v0§ZR“›ù”ùƒ/¨ï¸¹ãÛ­¬F‰°UUº®çƒ}ù¶ãšº´È$‚XØ‚Ä&û[{›spÿùÆMK­ÔÊΧI¸P.E¿\RYÃä`¥Puî ‡ÐŽy¾!P Ychä}Riܰ#¿¦àqëƒ"& ñÔ°Ðè®ÈÁsaŸAÁÛ߬jò Òh,FÊ›\÷±Ã*ÈLnutݘ² 5ÉÞÆUZ%!^0) ¯—kØâئ»=‡¥„*‚æFC¤ŽFüÞÚGë‰VFF]/:u%*”ÜØ]Çí…ÞB¡Ý‰ä© ާ¾ V"MzAEÔ_k zß¾%¦Æ@qFZš¡eŠI&FÒ©•UÈ6.}O|H<ú‹\–ºŽH? &Ø"¬¬´é ÑFÎÞR¤ÞÂà1Ûƒamû±ÄI« ¤J*b=C9;ì?ÓŸ¹åY’8á†FÔ¿3Û}F÷úù€ý0)éÄ·emAØy”¿=ð`«âµhˆ%K)7¸·~ob€Ù@³ž™×}o\6ßB |˜®Oã|:{tè3:j¹|ÁJªJ®Mýw#nÇØãê¿ÄóŒò®’hÁžbÉ8mï»鸾øù_Â>©ñV}A–¨êÖÉ¥]Ö$·™ˆ=®ú´¼;G–I™¦`¹‚QÀYLztr=lßNøÇª|#v‘º&ȳi¼3àü¶šyÅDïq× ¥ØVOkŠÆaœÖ×(wŽžrUÊÝìñ’§e÷¹8w˜K_ŸTšÉ] ¡Ž="¬‚ÞB¬¢üǦ+Yµ=1}tâ–H Fü¾¨gÔ@ÐËµÅ¼ÞøÇ993b6WëZ¢¶’QÐ0"(…U\þmÈQ~ôùÿ†h«ia¦Š¿ªñæt”CB¨m¤±`ã{m{öÄ‹w@“¾ˆü3U µ3äùƒEE]L ·;ã™çcâÿ|C5Z³+SªÜØÝv…¼§è1q–še5>’±ªF•ŒXs¨Ÿ” ½I°Ç"üFÏ’J:_E+Ån A &ûm÷¾ü[C™2ñhæe”›H]MÚâÃëBÈ­aµÁ$Xo~>˜ ºK²ÈCÜ64#€à\€Æü”eˆ+‡Qªálnm¿kcYØÏ»›p0\–S ,Z÷ßßlFð”•lÈUŽ«†6>؃YÈ)™œ-Ø­€ôÆ„!]·ÞäâCbKhרã4¨#Ì®6õ$%$U qÎ1îÌ]"æçYãK)bx6ÆÀ,å‰.!|ÀõSqÁïÔÀA‰M™½®œ‹Ž>ØÚ4qw º?•NÛaˆht…WP.9Ûy‹ºµÞÇkb^˜p6ì5 ¬1¬z¤ 1çýû`Ò!ãhHì›ê];‹ýñ Òîmk„î·÷ÆË¤Fl·¿>ØÀ •B°îNÆ’2©a±Œ{[€zrYG òq°Euлi&çÔsЬ"Ò0'²ŽE÷5KF– äFý¸ÆcË ±×þ.ݱ˜>­ñ‘Ì+i KLÆIUÅ–ößv¶)%švgZ…¥PH:‚ªµïc{{àŒóÄÔuÒ2C= 1³$r=‹I¦ÚØ‹kq~Ýņ)Þ#Ϫii™7;¥µ {Ÿ_þ¸èã“två=¼°ofK-I¡£x„½…†Äíûâ·„ˆBá»\û¾¢Øß‹ÈìF£rtîwçÐcÀÅÉ]wPlú³z]mo¦Ç pبçežù[< ! ØñÏ©õú½½1¬Šî÷V] W[m~ØÚuHE/å¸.-·°â>˜ Õiù…Éû^öû`ôSÙã  (o0ó®®Tz_é2 hS}¬/ß~xÆ]o`Ú‹ +°öǤ5ÉŒé]>c~¿úÓ†FŽ×{¬6ÆôrKx–”tä_F"÷·ÖüûcÄ]®-bÊÂæûmþŸ¨õÆÚB.ÎΪ¼ÆÛûò1ÜEÙ~ŽQY—DÔ“t†¬h±cbMïï…‘¡£ŠL´ʤú“û8ãmð¯Ãµ¿ Z°Îê`s°k·×éõÅ1©2—ÚÚˆ&ä_Ž,yT¢¤O,Id9B«cnE÷ú׈fèé…™žÀ­¬v¸&û‹÷91®QÓ ÁbHí͇Ô~˜Ïš­ÆE–„K Áf‘PºØ¸ävØàŠÃTÚdy ʬeÊMýxÛú…qU´UÔ¤¢‰‚‹=†”»/ƒrv¸úaµ7æHV`dÇg úµîKmm·'œ][uô1¥5©õ,¢kË È;“¹ýðtŽDEäžDÒÊ\[ªÞÀádSÀR…"]"(kè±×÷ß ëÙÙ:–+".¢$]/m†öî1W̲"$éP IBB Ç{|»‘û_)Á’1:•—qnã¹Æ²Rõ«RµA.U[FÚm§Mù¿;á‚è…¢–­DrR¾m”ØX[íkûá·/N“³q4Ô ,‡]üÚuêU¹;ßb8À/#Ñ1ˆ£‰ù=;X¦ûs‚¥žQ4S¼¬4 eóbè?~7ÀòÉùZÄZE]$‚@ÜùÿlDžâH޶ ?ˆK"Lç^­+p6¾ÞØ’¥¢–XÊ4®]ÎÖÛ·Ó`-ï…Qˆ’» îÒSy¼Úé|6GPÒPÆ5=62G,x¿·8ic¹å\ÖhjÅørª±¦²\|ÃØ}°¿4®H&ž95¹Uô:¾`7¶ßÓIi)æÉ`¤-Õ¬xíÉÂʱ­T«˜–b²h6(>E=ö 1v6“*‘ Ñ@Žem$½®Çn7øu‘ÑÄ! Ð Ã1$Ü{]Çí…9¦¢¢’®¢6Zº™:+ „*/æ6Úä#ÚØe–™)rø×®–’U°ÕvÜ}ÿ®u\Ì& ¦eÒ³H²’ÈCÛt[q¶Á¸æÃV“Q‘JÔìÖ¹`M¼§é…½-T—" )u€Ì¤Ÿkí‡óTTb¤? ú£Ð»!mï·¸[âžKRR±%J¢Ç$²h´Eæw;Úànæäl1”sȰ¼ÒÃ3‡óôDdò·o¡ýðc°†«ã!‚KuC°] p-m»~˜‚¤ô+’gr®[R^[˜ÅÍØŽm°û]Ä|*!¢Žjddxä’rIRR@àþöÄ™ÇÆË O:h³…FæâçÝ8Œ!–AÒ’¬]›‚YMÜ_ê>½±cuh+Èî7-°¾ûúâI|B9m‰¶Q1ëHÓÒ^=/)À ¨]îHá[ëIõBõîf,À¨#Q&Æû-þlJ¿—DeêÆÌΆK;E¯Üÿãô¼µL)LRJw ‚KH¸ôFmäÕðe.¿òÌh–%=5Ô¥#ƒö¶¨wò„oR=Z•¬4¨¹oAüÇì}ñM?Ã̽[±Eôº|Ûm½î0Æ)’®™§ZTŠa5¦çÊ„j>¡u Z×ÔáÓô;«Ì h^úªÞe‘È °;ó¾脞¢jevhI]PJ ¹¾Àïo{ö76j†Ìgø©‹É**¨2ƒ¤­þÖŽšCT³|ÝXUÒ67¿#÷ÃÖÞ¤RÔHU‰ú¬ìÈ&—¸ôíÞø[T(cˆªÈ ë(VÜö¾Ü{aÇM^iâÊ’ÜÞEsÈíïï„õô’GP"›òúd4„/P¿}Ë~¸d•ò$ˆ\§ÄZFrñÙÀÜS‰Šº¹*Å!Y×Üé‰ X¨òQRó$/«P¾†° sÛÓí‚"Ÿ\, NÉm* í›X¹Ä›äˆ ¤Úc•Õ„L×%£Ü Éý‡öĵZÞh€e7 oí‰Zq*™J®¡¯që{{]†%‰išúr©D@t…¹$ö'×¶ÜydÚ(Yd³Ú冮yûblîÎb}®äZÂ猠HD’kXÑ®6ôäïaŽ66gI;°¸±ùyéؖú ,e’ÈšIÐt¶Ä¿íf¿ÛSÓ$ÒÆÝDR£0¿ÖÜóˆä(ÊÅtFulà’mŸüœ{4‚ü£Õº¨f mÛ…Xù»÷Ä|r:<­E‚¸ÙXôÉ7v‚>¤~¸‚Œ£Ôˆœ)%À`Yœev%pDé$ZëÙ—¦šâÄny°SoS¶GjyJÇQ#€Ö`Ö¸S¹aém8eʰ’K,Œ ²j rW@R^üí"§š bwbÚYPÜ€IÛîo‰#Ž6x¡3C$hÀ,‰å&ÆÜ~˜èß‚ž¦ÏüogË`jRj$žug:…ŽÝ¯¸ÛÚø]ÔÛ&89N™Ðÿá‡Áåy}O3#Ó¨¨½%<¢Å#fbx¹$]±Ôés)ic7?Z²,è±·ž#¸eÞÝÇ6897ÌV††¶5¦$™]%BT[hø !ðÄ+[—WE—å‚’têWJ†°Ü“bJƒaþ,`›–GlìB £ZZÚˆrª'eœ©Ã.»Ê€†åI±ar@ì0-8©§†žjÊ¥Uª²ô– —µ›Uô÷;\.k”ÑfÑä¹³ ŠÓæiâS·‘Ûc¹ÀßˆÇÆh2ï EC¦©=C Ö©r|‹Øù¶'°¦nÁ«^¥âÒ¥!Š1+TÏ Ù .ä [÷ÓŽQø}—eÞñ–cálˤ•Yí/S/®e!eÿñ¿£\5­ó Åðé³ßøÃÙE,Y-m})¢³2·PF5v[û~çÓÓøçðçÅTôÑx¦ZxÕ+dq C*¹½‡òê¶’À›98ÑŽ DË–Osäð2’âÞ ñ n—U­š,Ó¹µ5,0Ð×ÒÑITÔq¯æÍ:hqßK‚§ˆáËÕfQ—ÔOC@àÍzoÓ,åJ;iÚþ÷ÚøÅ5 “˜³“ð¼dKRñM:eW!HÛ\E—ý-rh·x7ø«þAOðp½U<(’Y«Jû Eý®yÅC,¯ªð'6ª—0šjºéLQÕM¦òH–FÒ>fàÚÀì1çá¼k‘g-“»åÙdîÔ‘×ÈX$q€«#!#€«Ï¾,¹W¼–eÐIœRfm•@zZ*Ã’T › ‚uúa¡®EÉ(õf߇ž̲Á!†Ÿ3’hUªZ0«2³H·¾+ùìTôÙ½Gðú9LIfÓ–gÒšálmïÆÑxÀæ)[U”N¹ŒR+Fý(44vîÅOïŠç…3•›9z Ò¿‰‚dP.Dñ’l}ì,>Ø™x¢F[—$ù¦sçqft­NÇòDì/° Üß¿ôÇ.üVÊ¢¢¯8¢5‚:Ì|]­m±{Í#Êjàš¾Ž½c1Ô“ 1 å½ÐyGšç×Ó*Lâ¨æ–dIcè¯ÄI©ƒ¸½ÎÇaÜï·;bÌrågŽågŽhÌŒK¬š—Oéˆãyú¦P²æ+°áïßøƒ.¨ Ì¦£œj•PÅ·>ƒ{0=Ké*ŸúdîÝ÷ÆÕÉ„Ðr#&ËÀÔ9ÆŽ©o lÛâR¥n«3 Á7[•ÛˆÂÝv¿;¾ tH¨£¨Ê5ªmôÆHìcÔ£È<Ì4“o[ÛðC6´m$Æ Üé¾5D˜'å¸Ê/'æû[$KìÇ{_ØcRŒd²9P¬Ü‘Ü\f é`ok78ñP+_«¤ßve¸ˆýñª¥T»Vâû‚>˜Û  ‹Ü¶úvÁ4ÀtYn–µÈ*7íúcΛ(qÓ(µ‘€Ê…’DÔ¤é¸Sé|la$ Π@Úâ×ß®'&ÑylV÷b{ì1$e dhÂ16îG?Û÷Á ­uc¤ð¶;ØÙÕ¤Œ#ŽÆÊ4ï¿9 [I¨òY;µïlKU$u ëó¤`X ÉZþŸ|@nbU+§S%Mïk_n1$w7³ ´•ÕblLʈŒ25…ûchD“ EFº9 {ooôÄ0xA‘ØK½Ï6Æa…D±uZ@àI¨ª¯šÂÖ±ûc0¤,Žk4êðS¯J=MòGc{úmûáy€™´×Q0îwí÷¿ÛØé$£gÞ÷µý†þ¿|Gd²³DB›’÷ØlEº5JM¾YꩱME7çtõ6àÜcT@d ¡5¤“qµì~Ç…t²nm¶ØÕŒMk;k½†ÞÿéˆVGrT‘åÕ{ñ½­÷¶%e*» W$qîöãÈ>´]{é¹Zöþ›ãÅ`Æš Ž,ç±Äë²H$ ®¬.oÿM{{ý¯÷8ò é’ Œ~m€íÈýAØœjÙ]4®¿-…ì¯ëcöÆÌ "•d^Ü}ñbº®ñ€ÌA*OÌ@àû}€î5BE-¡I7V Öà÷¸>øÚu)LȦÊÁB ì{ßï‰)$¯™™-¬•ýûñű{,ú@XY˜åØK\Äi?®-9eD5´hºlèÝ8ƒ5‰‚OÛ÷Åb”3Ũ4ŽQïÁ·ôÕŒz©iSº€Ð7¿¾pSTö–‡Óô§Œ¤èÇA¾¥{’moíR¨|öU‰–åx± c)d9Å02*ì ³\ö6}pDÁZñ„WbKk;rlqƸeÊ\ZSI#²“gBå6˜)±ÞÝ·;~øwx§hX¤ŽÎjˆÙ£[{öÚø©A["ÍÕ$ªª‘*`E»[é‡9md ©Jˆ'QVa©IÛ·¶¡÷ÅY"ÒùFe®Ò:¦iÑ j@f³›\ úŒX)f5• ÉxJV°ÒÍrÝù$ÚÖöÅMB|,h“²†ˆ‘ÈàÕLX2w+ hGM#¿˜ ·ûë¶1ʨ¾2¥3Ë5ÕLæÔÛo}¶ãÛWHhš±–9LChÈÕÔ‘aô½ðž‚¯PS6©X‰¨@P£ÓÂå©Ëš«ÙµY­`¶>»’1S‹í'Áâ¤ÿ’e"wQm:°€oÿ·ëh*žS¢hõ]€cgo¹ã`Ôa¼5&ž­ÖycW’çH'k[p;›\mV‹jÇO‡pt´¦×°:H ÍÎ,‹qì©òÊ£¬µSNZ¸Æ B&ݬw"ø†–¾9«cŠ‰Ò¢– CH<©ªÛóË /ë‹oI•U[5*T´’ܤCS5€6ãpp¹t*Œ^˜¢1€ùRä‘ê.KqliI´PÓ±-^gªHÄÏ1Hï$q‹±“ü?\ ­,¯Rz2Á –G*  ½ô8zi窑¦HUZý.ˆ¸ ÍÛѯ¤ØzaÍ2JÔ]y Òʪ²y®u^Ü=ñK„›|פu©T^WM}IE¬ÈËúúcÚjË1 ÕD‘˜±&ÀíÛXý0lQ(ÜÈ# ÈLa±ß| ;kŸ«LJ@YÅþ%nÜU'%Â-i0I™D†yüññ¡”Ù×Qû÷ý°²±R¦)ê•äøwb/b,u[b0§ò‹H&Õ¡œð éúÂ鋪AµÉ.ÈMÉbR}8ï‹j™ž@ÊÏçŽÌ’HAüÂ@M‹ mÇûp6Í1aXÑ–=Qßp ¶]︹<ìpÒ~¼rEª)ˆ­•€Ð¤Üßõ'é*#?Ãcb¦ÿ”¢Ëp ¹<ï‹"Û讂ÄMLÑĨ½'“P²‹í¾¨ŠU™¡¢–*iI.ľÌHÚþ¿(ýp¿*`¯$3 Ì^FŒÜþú_ Òá–$é¹ùUÜ^ü }¬12:kâè6¾¾ ê:oÕ%”7sb6ýñ­]êcˆ#Œ('NÇQ¾ê?\Å"¯¥Œ,u ˆ…ÎÀ®Í©dI])ÉŽXcF·¹g݋ְÊw ½Ñ °ª~s˜Ü Ø•¾ÛwÜ Hj±^exI˜³Ä‡Ì·7Üñ‰'žJêá”äÊÒ i¶ ÌËèl7ÿ¸`ªŽ$ê)Ÿ}G ±SÉ Ë[÷¶#{P±à*¨Ìð<+1¨²0¸ W›ß’°-rB•“G%#ÌÑvšößïôǵ’ff1ÓÄÀ‘¨…b %@÷ßÔo„RÓ´lñ¼ÎæòJ@$^÷ºƒ±$m…Mº^ÀU*ô¬ð¿LÉ!Rú€ˆîoô_¦5™âžD@ÎêVà±òÉ©wý.lYÄdŽe¤3’îN½ïûb héh‘)[Y6y>¤ƒöÅÕe:¦¤G3­8I¤@C¼»&ÅÖÂäÜÛŸÛÏJ‘j,HH%îC6ŠîO­öçŒI@ìñSÆËÒe`Ê>[¦×÷ý°$ý4¡W2H%Švd‰¡»©½¬/Ξø ¾L¯ƒ3H‚ÍðîÒÈa_$ŒÂ슢ŭÆËÛB"y:4°J጖µ¬ ý"&z¹‘¢HÜ·U¤¹ar×ÒI;oÁ7æÜb Öï ¢THAy‘köýF]Ðð|æ²"<‘<]VÚÇk±:¯þ÷ÛR ’–YZ¢öŒ¨<Ê¿¦›ýŽ5†Ehš&e!®@‹úóp9¸÷ÒÖ~”ò¶›¦¤@y,§kw"âþø±¯DÀIYF½{E(©C€Uÿé…I7Û‘~{álÑ ª 0rDŠXÛmùÛŒ%‰5¨‹R•u:î?šÃaêA¸úcÚ¶ˆÓ$r¢)xÏ äy¾àâ%nÀNÖ=5iGù4îÜ/ü¶¸>ø#ádšˆHÌå•®oåÓê}îo‰"j… SýP¨Í¡ê6äk~˜œ¤2H]a›YG$±7Ë¥ˆûñÎ —$$:"º¶Òx-ë·× ”Í_QLÐİDQe –ÔÞ§¾ä}ñ®ºifŽhÜéž;VæÇ~ØWJJ©àª”ÊBê@1iºžw[ÚþþØWraŽ 1iɨm{ÝMûloï|k›Ï0)ʲƂÅ6;Ûaïl]›˜mPÅ¢h›T1#¨+¶«zp?›Øá]B<#¥© %5”°¶÷~ |2M2¹…°É1—qó&‘kƒÜò?ý,@öMº,¦5î=I#qÎØ&éØÕUV4èέ"…K€½”ÛÔúãØ:rÔ6‡X£!]Øéa¶þ‚øn¹`³Ig¨•\¡‚‹´›‘m‡Øûïˆgz|(dÒàå7ö¾ÿßÁ£âºQS³D$UÒG˜ù‡ÿ8’lª¶³6j*ZC;‡Pl· Ÿ^ŽÿDDÛè[OK%B#G”jm¤°¿ØcèïÀ¬ƒ8_ ´ª“ÐѰ/¬?žKÜ3Xw°¦9ß…ü#$4‚˜å­že Y‡›a{L}#A™å¾ð¼M%\Á "QFÆnžÂïcÇ<ñŠsÍU#vŸߊE'2¦¥ÊD“Uõäž8Âj7¹ÖRyïúàäÎ|USáÃM—S34®Ì±»dPl5ç× ³†Ík«ÅE2TSR‚e’Z¹ »yˆ±7ãz\ï=“ÆQd¹\‹$¢#%mFW·ÎAÀ·c-Õâ÷#¡þþÓåò¶cžÖEQZì$¨,$eîÑê½´îwĹá½/Ç>iø}âh)јŸáäüE;K¹ ¿)}0fU/‹<[ EH²Ü•£]3¼¬%kÿ*í}ûßgð^MBDÐUÅE'@,Ð,ú#˜.ÚÛ¸ F4yqšº3K$¢øg4Ë|}ø—á*zÔñ‚`­ž)UY ¨NŒ@Ô Ø/;ò7¿Òþxñª“Å­ð†y+¨5M ÃæÜY#: ƒÍíßì—Ä^ñFe˜åžWÏj2Ø^žD’ ,d(cÍôžx¶öÅ?7Îtó âƒ,ŠzVh¢‡ªÑAn¡Ž Zûâ½Ò‡Úá ·O©ËeË|eÿ¾0¢Ì<;âÎò Ø– ÒÔŠ¶-C«¤îX‚{vÇMüYÊrŒê¿Ã߈þÓ>yL¥Ú1fRz¥FÚ´Ù¾Þ¸[,’Uø µ’D›*®Ž¦ˆ%ŒrC%„Ð@›m¶Û‘€¿bÌSðË#ðÖl¿ƒÔÔˆeQ»Æò3…7=¶·±\ÙVLtÉ‹Ç1äye5>SNñ¼R’¬ ]ƒ•lwÍö¶)^>É1®¤Ê ¬‰i^¢5’ç€ÇIÓcr-·Öø»Ô&k9 Ôž8”‰•#@«ªäXpoŠ®{•H*¢¦,³J– ˆÊ³²ñsÜ[~ØÏÍšfÕôAøíœçYˆ2OÀßÃrrÊ ↱áMi™Gåê¿MÏ©'œ—~~~~gŒë³O瑘Ùè©ÁciÚT€W~Xá‚L´ÿŽu^-Î(zé5dõÐ÷s.€±‹ÚöBM½¬7¶,”´5u‰WUN!\ÞY/)špæÖäÛùúÇBYI#"ÃvÙˆüQVa©ÊüàÊ(J¢’úD’(7·—Ô?ûÆeÞñ%Fo—ÔÔ ²BºÕ «*ÚÅ@îí‹5$9µU JOгÂ4¬ÿ"B͈¸ ìús°ƒ4ËüEYLù}ZFÝhá­iØŸ”6ŸË w¾+PßÈÔNMã,š x¹ªja„Ræ”Ç º+.Cq¹ØoMð›;«’*š˜¨úTæ;<¥EÉ7¸`¹íÈÅÏÅ”qÑä«E^òT,sèõnËÜkcÏ<íµ±Î+sÓ ßâ|™Ža \§óÞ$Jѱ–#›ûb´²ØD¦`’Mˆ6ÛÐᇉ’x3VxÄaîê !Iïíô²†6dw=C¾ÂÂ×çaÄLo³Æp<Ý3¦Ö>]':E¤:ë7÷¹[\n éFgåK\¾2c1‰J+)ÛùOc‚€y%3®ê‚ª– om…Ž$Š–'¢–iÕÔ^ýA}6€£ëßÞ8ä¹fê! –àÿ³|HÆ7q|‘’AÀƒc÷à~¸±ˆêhÑfÕFáJ+TÛ hè_‡å•dš7#N›…ÔTy¾ÅÛ Œªµ-Ò‚M˜Ç¿®ÊëZ’’¦.Z µDÔ/xέ½ýøÂÓ÷ìYEKëb±¶ä‘·{ïöÄU  ÷¾’{Ûœ1©ŽžJ†F7B:€Ü€Û½;⇩ ÔWW˸߱ÃõÀi åböQbmbÚöÄ´£\í’=,XmÎÀoÏöHÁž8Ý7¿Î6f¸Ûl]Jiê­@ˆlãc{zzˆÊIÌ1¼ñ•¤Ø—*ÿÛO%;¡ ªÉ,…Šßtaµ…¹íƒL2 ‡¡w§g„•P6Rµî6âüâ6A¢ñ­î9Sß`>˜€!‹IMMçQmÈìw¾ÜúmïÞ`#ódó«: ä‘~ÃN}q+‰)ë”ÓÀ2Så\~ö?lyWM-.• n©bTP>› â @ÿô짤Úô’E¬;{X~¸ÌLŽ6e.†D@÷¹ãpq˜„'ù=…¬Ì[Ër/ǯl{34÷y ‚*¥É·Û}®~ÇM©Mô]ǡƱLé"ùNÛS-Á@Ìt)µ¯o ¸ #P«`îwÚÌ,m±·ß²¸éô‡\k\‘q‰DÊ®‘³6¤]µÚXq¿}­Þ-hÎŒ¢E­¿™ŽçŽ?ß{,Ю­ª›ì¼ÿùÄ€`îÁšö 4ƒµ»ûãC¹P†Óå›ÚÄßéµý9Ä©`£¦§Q%µ¶÷7ý±:ìm¨†XTÆ£-öa¸¿þ˜‘üñH€n\Ûc¸#×ÔËÉ7žiF­®O>ƒFAÔ[tÆ{v·Û|AÍ·q‡Ôu˘ёP¥Ä mà w<[c©QÒÚEì ÎÄaµ$"uD6o"›éý072 ª˜$WǦú¬¤Ûsö'ey˜J’$DÔÛiÒ©ÚÇ÷ÄÍÒeI䕨Y¶–Ö'·ßpqíd*Ñ ˆUž'µÈ)¾˜¥¦¸uòZòÚÕ©gPa%¢ k6׿¨ßO>˜q’fpTPÍ LÑÈì¿õ ]6Û÷›‹oÆ9ÞQ^ô²Æ5*˜SP¸»p6Ûk_×::…ŠHêU`ñ’Èà Â×s`ÇoôÅ2ÄYŽG@ðÄ1ËIJTBEÔ¡Üê$íkM»œ4©‰Ò‰ªf~“-‰±˜}À±.9߇«9fHjz’‡Ef.‡]Ù†öÛ¾.tù‹Ôåñ5úë!ce°dK0 ‹ Þ÷Øc+ÆìЧÀΜƹh™•d´òº]͈íüÇf=¹ÁÔÓFa‰š ™’ì­Š+ü^ÂûaGĽ2¥H£6 hÃ_H"Âý‡7û`|Ñähžbì“ ѽ渚“qÿqý0vr…Ý]æùŒt4¨‘B°F?/A;»Û–ä/Ûèq^ðíF¼¶¦lÆG‘áž^šIó Ú÷ ïÁjŠÙã™f)%@%mgF‹ók_Pâþ—Ã*4è gXÌzšF#ʸ'k›ì~ؽ?B©I¹eô±Bˆ$DШÉ˩ܛ”†ø8OÄ]faÌÔžÛnyõÿÇÜaŸMž(Q”´3]nÌ9[\\nFã÷ôÀ9¹SKy!Õ™`Æ÷*¬^ãamŹ´ßCî ±1„¦++1Ž1Øj;œDÕr%04ðFâàÊtÆ¢úãtsJ©æ.Tyg1ß{ÚÿìqìÕ *ŠË!FÚ¥±,Ãå'Q·Ë€´×PÃSQ:Çñ¤Qêb”†µ­pv½ÁU$ÑÂÎï-™Úcù‚Æö¸õ¿Ó 3ª¦«x5,‚XÙ”B·[°I>ŸOðàyšxTCO<ŒH°PConçÍ~Ûàß¡T‘ u?0UaE {Xuö&ßKãÚCSñƨšZ6Œ÷#pÆçck·¶ —,¯c>—’I#RY&¿˜°XY†ÞØ“%ÉêéËÉ^çTlìúYt‹ù€]‡ÐbËQèNEù:ǯˉcÜï~=v¶ M ])c¬îÀ‚B•&þýýðeyãÔ¬¢’A$­se%mp/~×ØØØï‚d’ )¤”ηr\‹noìlíò aQÏÓ­Z‚úO²¹!®Eû÷ûbwQM;ÈæQ%IºÝnx<ßÓш|s#¼ÇXŠ6i$ |Û;zú8y%4ìVtšxHQ Bª¨mqo¹ßG¦è—%’¨fŠ`"–0Îóm7&ÞÖ$oôeBñVÏ,?ª®×V‘ˆf+³ð9çë…Ñ×ÌÉ43ZS3%ÏPjÚÖí½¾ØÚ‚BÕ)˜ cL‹+²3lß(RAô»bÇw|({8ËäÉ¡¨¤ZhãRÈϨ«w÷;µð$EÝ‘”€¬À¬‘¹‘kmÁÆ•TÂzø¤[B’¤a´¾Ìö¹,}=±‚…^n”RHÑ4z¤;é]'r¶öÀØIO“EeXä´ò-Éèê3è%Mÿî·é‰(#fn˜r«"Çc¨¾úÇÜß±¨G­ZjwI£[‘Õ[X½‡ØýØW!šÂX§Y‚\]\Ýì4ÜÛq²àíbM¡©„¾bˬOH<º»'p/Ç}¹ßøŠ(¥xúʱHEеÂÚè/ï°8KM,‚•^'¿M‚ê2ߟå·Û÷ÁÔ“À¦šLÓæÊ%,H ×r ‹žlªmÇšøWYž÷1UJºêid…b¨ ,)Ô~{~¸k$ø™]ÙcÆì,¤¨ ¯ß›û†•ÓA4•STPÊ€ºº$Î53n'Óµ»_Û )ÒH¤Ò@QÚbÎрѰ¾ÖúzcBè;Yìu’£êH-ȸ[ã¬Rx…¦§†s$J o;lÛÆÞø%ü/ 4&?‰©‘!ubðª›< ÛÛ ó.c¥“휾 “0”‰êDF&*Yo¤i°ïÇ ¾5“#§J‚’HìŠAXãìÖß÷ýqmÏ䤦žJH¢–Y,‰fÒü•c‘å©QÑ’¥t‰v@NÖã}ð<ä£ÉltépU©¼5Q=Rf•i ™÷#‘lZ2\Š›,øv§£•ÚR7 TÙš×Þ䓇µ”°khÉ´Q+gQ"Ê9·©ô8šš’Ždy XšÃQU _skz[§e±ÇŽü5•šŸÃM–ÝÂ"èi*µü¤ûluÛ#£¤¤©–²ºXÔ*Ä%øxÀ&Ý»³ñbÖ°°¶Øç?‡pˆ Î ´õu4É,#SÊUNì ­ØzbýàF¾IâŠ<î¥b uB&ÊJŸ˜ßcé…§˜°jk”Y2üö“ùM[IE•ä0»"ÍDš¤qþ#qçâÖÜï„Ô5­Sâ›eu9†S.€•UD5ä+/!=ý=°Ö·!Ê2Ì­h²1P”ÎäMTÌàƒ¾‘'{âçžÊü[—xG5¥—'G†6zúäéFñ2©wibT²®Ýöí…É1pY£.Ajk¥°GBD”ÅYÒ" Øj$Üllß¹Üwà $dú¡©¥XYºqù®‡}üǽˆÅ¶¿!ð¬ÞÿüFgM_4Ð ¢D•YL6$8P~R{÷¾9w„ž¢Šƒ*¦ ¦-Cï—¥<B´½K†ÓÈ`€xýq\1¨ªh¿ÌÝ/„éÖÒ®LÐCH«%Écv¸b/oM°Ž¾£.ª½-Uá“Y}a 6$¦Âý°lô³ÓfTñÔPfDXê•a20¹6fù@®øöŠ:v¤­¥2­*»+·Â²ÿëoÓ B%y Œ©.ä±`$ Ö#¾Ü[ a‰ŒñÒÆ &MDnvÒMÎç‹b_щç™ÈŠBÓům7¶j’JšŠ¨¢º´ÏÊ(b«o­°ÂÐ5 (KqÕ7{ÚÛ[úb:•2M( vî µ¿[ïa‚z‡ZUÐImªû±¿é‚B&_C4MZi Œ•"Ê£ÓêK~¸o‡¤€ä`]ÒÄ•RÓ}Ààô…_JÒA¨– ¬âëknÀpÇ"EuÂ[ WƒhÙધJyõ³/•AîNø•B0ºŠ Ž’ %R²Yt¢Ü*ܵíÚäá*Å]HZJExŒH$’2uë³-þ›úaålòS½; ‘TÔ$ƒüÈ “ý1tôu1Ç,3Æ¿™óE͸öû`8C _UJ²)@%!FÊÇlOY=,ªP˜rur}¿Ûˆš?1"=l€?–Û÷ý±•-Ë*¨P9·Öç¸{,ÙL±Ó˜Z‰d–™™ŒÊ»¸Wô¡û^ã1H–Ei,#˜¡ÖmÇþ< r¬¯20ÌUœlÚwž7þ\\ò,Ú–Z`µJ$’%2,›Üz õþئX©6[Žvù/B K¦©’(ª#Û¤¬O­ý{àbV¤"-@‚Mˆ'›ýo€©ªr©êcu^êÓÓŒ‘suï¿©àœðé4ѬU’H^ÚŠXµ¬¦Ø§ak|ƒeFš¶ZX*+*P;€eŠ4±-«V¢GÊ4ï‡Y…lIÈ´Ð" +ɺ[ŽøS iE%M;Æ©–CÛ¨Íå!¯ÀÝ8úà¹LʘÇK:ÒÉ$¨¦ìt‹0bm€³s놥Ñ"›d™l’A–ÓÉY oé,LK1ÔA½¾½½0U|"©jH£mNÌëüö o§úãL»*ªJ(!’UÍ$ecXþX°!‹¬;áâå”ôñSšõëÕTCá”îo{{ßåE‹ ›äG–eó<°ÇQI>—ÞO1@‚ç{oL0l.eÌ+DÒ±&åÆú·2í‡óÓ˜¯ü¼0ÊâGy …”I'°°Æë•Õ7J:áð•¢…H”‡`FÇQùp*ËT6‰2¼¦ª::–SM YmJãÓÊÜ‡× £Ë`zhÞŽ Wžx‚ÇÓWISs¸ïqûaS˜M]ðtÖÇE ÌYe¬6c{ âZü¿Ä0˜ †–ŠHâ-¯S+mõÀûˆ£O]ô„2eôS‰Ÿ0–u}HŸ ܵÁƒn1¥,t« °ÀèÓÈ¿’€’ µÆçŸa‡ttC•<"’E¦C í,ŒM¬‹¹µ·Á4zš2éòÉ §DŽ6Ý[½½°~áRV"ƒ/­•gµ<²Ô/NO†ôX(ØXÜß·¸!è(Ýá•è¥S#èuq½”.Á‰ãkz†/áüÃ/­LÕâøªUd™’PW`¤6Ì>ø7Ãtt5y²D™fh¦XÙÝfeté!®EÁ¶Ûâ.É$º*3ÇMÏO>^µ ý>A Žo¡#×|Ù-NbbJ!XÈXl|¬ÄX‡ö¸'ÏÑA‘çÔåiéÖW‘KÈ–sm!¶¶äó‹ …hç®ë:Q ‘̱ÆC-ˆ;qí†ÝìG¶/ÑÁW?4,ª$ 㲞v¹7ß ¡ð*UƒMü;–=ÏÂæ÷ÛmþØë¹œÐå¯PG=+ Ó47"2Ûy½Á úâ¡HÕœJc‚IÚFD ^;iÔÌmÅ+†M•Ê¢øÂÕ³´tÎëðhEõ9v,.>¸Ê ’µ Ç ŽK1¬mfãap}8¾É—K*MQ¤!ž&KV¹ßÜêØâ*<²ªWs.–¨ê« [ÊË^O¾x¾II_yV¦:Èô ´dk¿ó¥¶Ä4™%w„Fâ(ïpT†ÈõÛnqÒ©rØ©c5;šQ£á¥V6ßIÿºøJjˆ:ޝS¡VdÜêí{ÞÛó¸žR]•¼³*£2Ô¤±RÅ!+¦WCJI¾ Ë{w·8Ýòܾ–®ž‚ž¢s%ÒBàÎÞbF÷mí‹{—ud¤‹4“«?^&W ÊPYIØœl¹m]E(†R*4ÊçÛ}CÛoÓx<˜®R¯‡h†Nõ5qôdR;5<”#{Iß¾#¥‚Ž8Úx¼=¬õUÀ¸Þú‡kž=}°þ¶<¾tWiAXï®á"ã‹©¹ß±À´…d£«y(5†P­%0ÔÒXÜ,Wƒ¾üƒ‰ó²Rö5#1¥†*AgRc†í#*Ôì;‘oSƒÓ/3‰)c§¥KҔá›f?Ínþ->Êrsá÷¨Z)ÅRL&z‘%œBš²êäžnFÏè©8«©†­h#iÙ–¤ ñcóc,5˜²Íã]®Êc–“‚\¢¬Ôñ,5R)n˜v‰u.°vv›[ÇÑŽ™º¤‰4=ÔÌïf#Ø.ÌÙ*JÕ4¹mC‚ LTÜ-óoõµ±-^[M×¥ž[y, ak¯ºóqëÆ5ð‹”,¯åÑe”ÕrGOFÁªK…(p,wàîG·Û `¥òÙbg_¬U$eù½©8aU–´’T‰âiKÒ·±D ^Ý®AÚL¾¼P´°ÒQH«v!H2‡Á´r¨œ ¨Ó+„ª+kÀ¦øiaŠB³Å) ¹³|Àß…oÔaÆk ™ =L?Ãéâ˜ðD™E¬n»òHÄyecÑLÙ„ Ôµ`™VR†ÃIblë‰3šÑš¼?Ë4±y„ÁÂFÑb,wÂþ˜IHe…w•j#©«™iŸIa*>[€l7õßWACIHÓkÊ–¦TVÑ—Ò{jV§ßœK‘ÔÍZíEM)F@Í0@Jzsc€j(%þ%ðU¥^$½ÁŽÁ°·¦ßrpŸRÝ´"ª¤Wš*úÉ)êêÝ4¤lFên am·ûaæ_M^(ã5BYŽ”Wº1<ÙmÇßg=yó¨e’•é©á Ê®©¤nE¶;oï‡ô” OM2™¦}JÓ)Di¸näǦ'\ £ÈðO^•ç\ëЌ<€è[M¤z�ñ½NK¦’ZÖ¨j¨™´Ê„Û\„îAî6Æ™<4Çâg¡’!V©Ó,K±7#kï÷Ã\Ê ¸+KxìªãV·ä1köïÎ!ix¢ ª¾ Š·¨žhÏåEJ/ÔrÀª[è–Ç[ñJ湦OM5LÍÞj™Uu%öR-¾«Ù}1Ér¹ªÛ5޵BŽ%µB(VßæÍ~F:ôù†^þ¡–d’ jˆDñÐßTÒª! ½øR}oêÛh‚O–gÈødÓåù=¹]4í$×z©ã}sʬÙÞKØØZßlT?˜çÿˆ9Me1lÛ)ñ.{“2BXÊŽÓÀ‡fœí!¶Ö˜*5Ñ\ågð'‹ÿ2üΛ=–‹4ð^cY“-.`Œiúza÷Ôü_¿>øé~<ü=Ï¢3x‹À9}Ml°±4ubÑJH@6ÊÖEâÝñJƒÇy¼å^¿>ðW‹écf Û)’Ž©@m,…(/ÚþØ¿Kø«ðuŸ"ŠXצ°Õ,ˆSH6¾ÖÚàa¥‚ùdŽgQÏ? ¿³ZÌ—3?ˆT‹–æ9Up¢q(¬à)Úç}ÎÝñ>qâŸx·Çu>ð~C´ô@%}}[Ú.-¤/ mÞûcŸþ3x§Ãþ#Õ™®bÙTÒW ¨ŽŠ£¨’i;±KÖÞþø»~øú‹Ã´ MSeµKU*™çZ›M*躳_pyú±Rû³üÆN\™ã å_‡~†¿Ä¾ è$ÊRZh#>`ª¶èÄOóGÐA|Wó:jx2º_ÃßMáêzxô¶kšÊ«Q28,aúÙ¬Þ×¶.þ9ñ»×ÖDÕ´9]-JDé‹F+æUÔ-¥šÊ Á"Ûƒë<-‘Í]Ís/ŒŒ®’iÙÙ”.¥'ü£ ±(˜G7l‚º j•úË5d2Åæ­‹{‘Ú÷¹>ûmŠâ-.M‘¤Êëâ0º4E„2lÄntù¹öÇr¦Ë¥PòºYzksÉ·?lTüá”›Ãõë-2T˜£r‚6º S~ Ò1T¢Ó´Fø>\ðcf±ç_ÂÖuž!!#¹);[רâÿ.D’é–ž6APíׂHÁê­Ž O°±¸à[,˜ÑÒøÞÇ––{ÄVk¨(°<ÿ¥ŽÁUG–RR–™ški ¹Õ¦çr{¨SnüY*q|ñg,—,Ì…*´º]ÃÂdbÅЋ©o`Ä[›cŠH8‹r‹©’Ûoé‹âˆ[;&¥P2G*’Çe%v.?ÂX ú“ÛY€dÐo²6­¶k[‡|HpŠ˜5Ñ‹…·,O~ÇúãÍ(¬­©‡ ¥E¯ÆÄ}¿|Na¦Dô‡Om˜Æøös  HŒ \ÜXú‘¿6Å›‘ ²èY s& ÝÀm;ïnû_LMWã¡‰Š„nI:HÛel‘Jï*;€¾ûŽ}¬xmjê²lÁ´ºÄ"«1í¸Ûï%\²ÞšY""Ä^7$6­óþ˜‘DÑ2y(½Ø6ö¾÷µð|Í Ï ¦Vi7W¨i*õµ°;Ž”=XX4M ‹™‰&ûaT‰F©3­KŠ)C«sÍïûàê•‘#I\Ư(d$3ܸ g2ON¡JJU”°½÷ýGl1ÌcXhËHšH([¯¿í‡¤•ð I~*–V.Ö$³dcØzaú…Uq5=`IC3xßnø-¤õúSEÕ+çR¦'q`7ílmGE54‚:³$¯©1‚ Ÿ§ï…±’D0<ÌŒQ/R±2Ø¡Üíþù w°etÔmC#ÔN5‰m-׿zóû`9’)s,++ mê@"ÁÏc±?ùàbjià–7xÔCPïùª\«qp¶Úû¶‡†Ô¹'H)jrÙØ„G8R$p¬„Hö?ÊMÁ=­½¶ÆÈc£¦§¨¤§eè:HÑÌw!läûiÛÛK¨¨”ÔÁ#ôÕQ˜fÖàíʋ؃è1½dÔñÌ'£tÚ-ÿŒXXFÓ¨}vôÂnm Ò||,•&–š¦­Jƒ+yщòÛíý1˜+(z£˜%uTMP‹+ã¸k ‚MîÜöÆa÷(‚¬­• {<‰ªÈ Úÿù/ƱìÈå ]WU{¸î9ÇŠŠÁVVÀê!l9Û“èë,ÒÈY%îtŸå¾ÿµðv·ê_Lñ54Œ¡ü¬î£×Öÿïob7º'RÍsr·;m÷в(“YÕb‡Ø_úca²îÆ×ÚÚ‰ÿæØ•@2%R,J•mÅÎ’·çúã)d%<Á”h±¬IïÛ‹öÇ«u,ÿ*oµÍ¬F7°UÙ÷]JĽñ6™Õ ÜÂnÚ·ÃkãjZ)+]DI!?4…¶²žmô$ }1ìQ¬Ò7 Ü6ÆK’°ß)4SBD# —‘ƒÜ¶ö°ôù¿¯p1>ï°š⥤hb*¬ˆÌ–7R<¶'ìoçV¦fN¤Ž¢(×H°ÕaÞÿSúã%‚¯¡Ô$ôæ!Rék ÈÛü þ¸2“/þ'›n«Ô]¸çÛ¨”oIKК{õ<ÇO•ü‹zX~˜ð­-E,•ІŠ&Ǧä¼ešÿù1&Þšw¶=JzQU$¹}r¤1FÀ®¡¦äúžûáíÒªôˆéFCyÈ7#b/Æ×'$—h©ÇFòNô²õe"GÐn âß\kð–¨MH²Â:‚NåT×ûß ¶Z˜èL³Ë4šÅÖþsµÏ°8Úe¦¬§XÝ¢}lnêÛÄ_í‹P¬ë葞y:Ò½È}tŽÝÿ\"f¢Zä–™”+Ø23lûöôÁÕùe:Ï2¢‰¤›m'¸ÛïrêT›¨±Â5˜ÅäpK\Ÿÿ«öÁ|¡@ëàPë¥Pvb …mÁ¿°·ëí…sUÓ»²-™ÌGmì?®ÉKQ¤’()T–(Ë÷Ü}ð%6Z¹4…¿-È7€.ûöÅ}NÕa”«`QòÚû},o‰¨æžš¡>¢Šì5­¹ãkm ÄÉ–»NNé2¡6uÚöÇÔ`‰<“ÒF›Ü…½†ß×o¯¨À»ì ò^2¬Ê›3ºHÆ6RªpÌÖ—7ï¾,TR~e*TÕÕ6¢lHQ"Öæãê1Oð—†g®™'©‚…Pie†B9`Wu;žGlu?ÄÔµ±f4¢ j$ ÔX"Û Ýˆ,DZ÷û yd“à׋Ÿ!Ù|‹””ÿÂ!•ëF¨¡ ©Ôùl@Üöõ8®IhòY玊Ij¤¼QÄYX–ض˽Ç?\8†läf¿-\/PWOÆÇfrªn” 1€Äi[^öÃɨj`¤¦›5v(ñÈúË©¯óÆê£Êôãƒj¹¶kŒAòlÊ‚‹.Š™YÒ¹€"42tµ #S|Å­Ø q‹QÄç¯ ¤t„X:KIAÚËr_ Ï—eðÔÈ¢'©¨i,¨€@*N÷½ÔXzaîGIK,˜J•r†k¥ÁU$‹•;ïÏñ“Pûd“³RVIÊõS¿Ri º:|ùTž{m†5ÙUlæÔu LÇLõF÷yRI;_qå·¾ È28ÕµC$ò´kj˜*êÁäœY2¶K¦›ÃòÈŠ@’2â%@[Þ÷7Àpî“¡Z® N]á©©žJUÎózó !YÙ sr@[nH¹ë‡ÑduÆ‘cªÊ)âTµDoaÍùkóíÀÃЕeµså•Iʲҋè#Û“ö?| Qâ 2Ê%‡?ËjÝiØ$]EpžûöÀr¶ éƒEᯈJjØkCÁ ùn¢Û€Ä_ôÁ—…–zÀ(sªªDrZYeX° lX —ok`¬£2 •à$Jú— :LÆ„^à}ÿÙÆA–xW+Îdóæ‘`,µÌʃp¿ ‹n;‡ÜØš¸æY]lTRåkYE$‡DŽÌáIqªáEøbNÛ[C–fÔ•ó–Zg}%c©²­¯pI;ž-‹†UU_N½I"zÚP‹¢dóÕ~o½·¿×n-…Yˆ¥Ík*šjy©gVeXj¬ŠJ’./±Ü7ÐŒ L^Jî_â|º·Ä‘åY—^Iiõ ‡Á ºQ‹XÚÖ?û°Oˆ"ZŒ¾ž–Ž»IK3°"Jé`ÜÛaúaõg…rY|Uüfе2Üà§üÊÂö(•û®ãoÄï ærd/ÏÕJ—Ä J¸ÕµÈþ–Ãp€ÈOàåΣÍÍð,µ5JP €†7 o—W¡>Š{á‰òŠJ æ©¢Y Zò¯$1›-µ 9›ýñAÿ‡ßÍ«1ʳ)¤LÎ*b”ÿI%õìûi¦.> ÎZ¢’¯˜+H§¦ÑŸ2¤r\ÛÛm?ùbK„$yìŠ*HM$‘JÝ$¨­ tVRÄ«v´¿>¸§Y‹¼ôfxR6°ê0°'ëôæø3*®¢¦­©Šw OCTd†Q##°”öØsï‡ÂŽU‚±#‹â¥Œë‹ãi.e jeîG®Ø¯—Ébi•¨ršÙežjÚgA8’7–,tÚà›Û¸ãf•.Ôìh¤êL“Z¢–K¦=· ïÞØw.oâ:LèE™R£e•¡žLM‰f>€ ~˜ß6ñ em:½KL+am2ô¡¸"÷¹ßl*iv_(0<ºŠuËÄ$ò^QjvÊþÁ¬vž1í5mõS©©¯¡è“ÐK ßfRw±%lIÚøySG•­ 5= ôò4Ï®¦6PM¾a»\ƒ`9¿;[Œ ñyU5d±õ(ºq•ifŽà-¬çŽñb¦¬W ðŒT•ë ´±ÒÎò4QÓ6>Vc`äôúc|þ‚z,Ѫk+)ºë/Ri/}ô¨öãß òŠÙ¦’:È+"diÄ”ÏM¥@/þnÞkû·¶$tre’TÔI=LæMM$ »lîww톋²6šàØÓÌŸÄ%) É0’4rA×r- *þäzbãÓü]LÒ½UH©…âyZ2dÒM‚Æ-ÆÅvØXv',¦IVÞš8©Þ&H™ÜuÀÜv ±7æÿl m ΩQHñ…Uêuu*'kì1r•Ê-ðZÿ³ºþSx-©UTÓE¤;Ôbäp,O“ŽøyCa›ÓÑ>_KYW5ROÔ!’4ŽÎºQ?ÆìUÉ7A¸¹Þ÷œC-nh^¦Js 0R ‡Ô"ú@¹úž0Gò£ÍëÎ_XðUæsž’ÕÒº˜‘¹Q¹{Üv»Ete–¹gGð‡k E Ï$ïŒ&«ê‡ëN\ë-° ¨ÀXx±·GË3 „B5z›éD°Š1mØ7¶ÜÛØâ©O]Eà,¨†²ê$(ž`ŠB¬J¢ú¤‘ƒÝ…À7ù¬Ñøg §©®­Š/„ps&Ù‹Ë!@w$’EþO|hhªè¶JÐ#¤õU$u^ñ€@[å÷ýð,“Šªw«–6Žp¨ûÒpkLrì³ñ&—2ñ Ff‘TÉÜ\F·6Ó±ï{‹à¿þ"eõ²Ç[*ØfPSDÀ–2¬¤©kv^7à)7°# i>HÓh;ð÷‡«³kü4QÕNJ-B Qe7©-ö¿ 3_TÒe”ù„ê–Ró;j¸$éµ­Æ¡úã\Þ§5—ÂM^•RC-ê%PGæ)r¤;î÷{àßÄù¼/ .YâX¦¨?¦  §wßf=¸ï„’ŒŸdPtM‘þ d41IJÔñ´î®ÒÌ_@ýˆÿÛŠì¿‚™GŠ©³`M ±Z¦+ém¨ºŸK­ÿ\uø‘=m‘’ &ÔxbB“qþøÂ¬ïÆÉžQÃOJ$† ¤é».Ç>ŠnG퉲¸²·emó åH””‰ Ð#ôu³öó)õÜûX2ÓWÏÐõ• U€,¦ö'éb>Øå^#ü?5wËg"D•d¤êËß`§QÿÛˆ¼9 ±¹ø–––¶˜¥@UÔ›éaìA ú6,‚uL \ŸDR³ fFFê:cH[w >Ø‹4¦L‰¢¬ŠZq ÿò½Áîó ínÂþئåÍLP m%m‡P(#ó/Ë!ãPéþø¸å9”OD³hg[-‡M€á¯º’-Ç®"‚ £æÿÆÏ˕Ԯ{•¨™Ý:’"FͨÿŽÖùòíè=qîMžAâÃ'žiᥩ‰6yîÊJ|À•¹÷¸ô¶;‡ŒrªŒÂ‘Ÿ+U4„láE˜nA;XŸ6þØàþ!Ëêi²œÂ™)R†IKË¥lš †Vù b‰Î+á&?Š-k2‚,¯*pÆ f­fŒ£†Ð_Ò÷mð²™ÓÊ8™˜• ‚Üúéýñ5\R†ZIå’0¼ $ÖVÃaņ<¤ŠÇ§óÙ€ÒQ±¾àwk°ÌT¸=’ ’®¦’-:\Ø\ÿ´¾¨ËŸ*YêÊdÐUw6·;ý;bJhš…içi Æ4±á®=;zûášAÒ‚’CŒ¬ À±ÿºœTåÈDpÈ(ô#|¬ï¥@à÷ÛlX²¼‹6´õRCP'3GM0-`†û^ÿËûá4O³|+2õ5ªj"ýûvôû‘ÜáŒUõAš–YzÎFU䆶½@–À_× r’ zÁN!f–¥Ô+²Äk‘m@Ÿ]´Øý0Ã-˺ÌÔ±­¶Ücq].ϸ[ù½Ç¶5`ùU”›¹½­Ïïc‰©o:G+7MA²­¸#ù¾¾Ãlåñ•+$¯vkí¦ê,..{wÁÓÉ© †Ubʃ¨N•QÎÛ[±”t’5\k i¤bײ€ÌmÉ·ÓÒšjÚcT¯ª4zÿ-oü›Xî;úœ2ç ¾³ ©8 µ uÅ ÔÀiöÔ?Ø8ÚI–Š©êfHTYd(¦û›íë±Ñ‹Õ×ÅMcL@¬±EoknÖ¹ÿdBš“9ª9”JÒLЬ«·³{ØvÁjºµDÔæ›ã–E¦EJÝjeÓæc£B‹öµìpË30––9ƒA!æ`l'NŸÞø®f²;9™`Xu»µÈ$½Ç°l´Î+RžJi;‰?'™¬æ;ño¦²·Ø·0Ìkji SÕ°¤X©Œ(Õm*M·ÒŸaî1£=4³UÔÆ°„êÀHB.[Žq#åo™WSå¤uŸ°²£o&¥òñ°®oïc°ÇBéEI™Óœ’*/Ч òÔ6TÙXÚáØP6‘{- ã6ZM מgbÁ5oÿ§jüµ(|9QÒȓȯU+°°mm`þ÷úá^i–æQghÓkJ˜Ô¼Ž¯§R›ä-É;‡Ö)ëói¾*®G]I 3ɳªÀõkmc‚Я‚,Ç-žXŒÑÇ<ŒªfÖ·J€í~0’Å$´Ñ'S!1éeQü‰ûbó5>fÔïL±¬ L"ZCk^–6Ĺ„äñ U;<”ôôÔÒI jWÊ@õØÛ‹á%(Å[ `çÑ]Êr*ßÕ¬4-L¢572\݈º¨¶ûnvÇGðWáÆK rÖg¯%UYœ+,P ÜÚæýùã¤ÊPÒSÁOHŠ(ËŒ¬Bnå‚›jç××f™|ô4Ô4/0ª•ŒI„ÊÑ.X°½»úc²9ônÅ‚)«Mᬪ)JÍ–Ã4€IQ•-€_æ>¾‡|A>º!–äÑÑEqÆ–d=XÅÅÀþPwôãÑÐÉOS)Ÿâ?ˆ2*å”»7©…úbÏáú)Ó\õU OmG@‡P}¬5‘kßžN)kÜÒ¢®¢S©ò2êê™ìôÑ‹=D2Úc#°º)µ·ä[×WQÃVO R& Ó­ìštùÜ)ÚÀpCÕÒOo%+´wwŠ71‰.-©‰íÎÃ}ñ>UFÕ1ˆÒ¾Bµ;H (ÙÛµ”snp–˜û+³Xi+¾)¥E©x¾XD,H«¹bOâÀûá…,‘­ešOn0wŠó¬ÃÃþ–¶Wƒ1…7/£Ì¡çro<5âü¿Å^š¿* rBXä@¯mÀämÏ¥±k6…ÝKžŽKøÏœf™e&a•ÁSÃÓ)*ä¢06Ô7±§n;bÙø{øƒI⬞š<êZJŠ•môDêê·<‚~ÛzaŸŠ|=–xŸÂ­O]W²TŤ wYAßìEÁÇ$ð§ƒ`ðž\+ 5J7\ÁQÔr%BnÉ Œ\2ßnn;ŒY½Uå‹sN!¾/ðòä_ˆßÇrYéŸ/QñÓ A•¬ÚZ;ÜFÇìqŸŒ,>§Î²EIš)ä$­sÆÚFµÿÛŽ™—øG-­ðäsNòšéè&’4·ÎæìH[ËÞ×aŽãß øªŸðò ¢L–°Åy:î ¹„’l„•]6µÀ°ÅK,T’b,øå)+*ÙßÄ<;\ÒÁP%–˜ÓIï"¡6ت‘~Ûc£ø/Æœ ¦Š£âªž–?†Y嘽®Çp8Øú}1Ê<%AW ~] ?,nýI&S­›™•ôÔÖÚûoŽ»C›,*éSE `JIll<Ú‘†àð8õÃNTè³8äóÃÝeLfJá¢s©c©M-¥–à+@*uÆÜvÁ™VqšNñԯóR»G<š‚¡rJíéß +3¿S,“UT ÈU":c¿–ûm{…ç“|_òlƒ(Ï<;”Wf2K\Ò£É!b¨¤³ b6"ø¢Rvɩɋ“å•üå**蟥1YD€#²ï¾÷ú i‘P,Íñº¥¹Pöô±ãGÊ’ÌÑçWfQ°ÒúùæÜûàLÏ;‡*ƒ„ÕÓ-,@r½‡|dÑæ“ÆßÌÃà³ópI¿FW5‡|1Yðq²õªâ°F:˜’¢Ûû)ýN6ñÔ™vW_”­3OÃþEÀfVÔo#{ ö¶gµ VrH–ÓÈk¤üªƒö¹"þø¸xÇ/§©©JŠŠQRV#›_bIàokž×Æ 6¦sÕ9?W_ØÇ¢›Éª”½Û_دÁÇ•ÿ-‰[•ŒX°$âH¼A"e“e9–UZQ_TÂäÜ_Ët#­·®ößS@Y0ÿŠÄ•õØ\ðyÀÓ×ÓJJš‰A¦™¡)ÜŽÅX[o5÷ã á|kr¿¨t*µ™¬M’æô’fòeÓ)ÿ—[MÉi¬™o·ÿ bj깡¯Žêj –8Ú0U÷ú¿L8‡Â4kZ™Õ=\ІÑÉmCPÌžþ¢ö&ø& ™j²É¢ŠA(‚K´òÆQÁÐN~–oNÜã½t‘ÞnŠNR³G/ÃÍÒIަ–V+ªúNÃ`{î-Üàè)3YZ*)k(å^†v‹¤ÞafŒŽÀ0b ãÓê!ª†/Jš [jUš'ób5_e¿›ÓÕ>\YrÚeŠ@Fࣀ·õí„ó>7ìgY›ÊÒé~ÐÉ3LùY**%C7Uw.,O>i, ¹Ð§f¤¬øf£©Ë)ê´­bÈ:ÉmGV– +yóŽâQO.Z*.–™ÉŒé×§kX‰‰?lV³餢y<$”¨‹×{\|ßlW‹&ïÔ]^G,’õä9ÇäÔS|®C*ÓÇ¥¯…€»Ü.Ö²íÆ)Ÿˆ³Õ¥ÖTSQTJˆd¦E ‚Ì Ü±ãù¶÷Ū’¿#ø¸éŸ>¢jÛÚ(tM½É(Eíac¸ÞøKãL¾Ž*7©£y§™#صõ.ÌÃçäÛlhMZ4ÆÜ öQ—ÃiÄÌòÕ©ê’Ç(ÔØ\Nq µ‹Lg¦œ¨–¡nˆÇQ°>q¯¶dô´ëIfV©©a4ì²^8õ0(½ïb.7îG$‘GX”¹dtrÏL$U# ¥IV‘œÛåµµ}­‡\²§ÇÔTõ´9ïÁÐKÓÏÖÂ5»+„m¶ÒÅSWL"˪VV¦iA¡°½…‰°Üíéßhék!©’¶,Æ)§k)3Ñ;3ž<ÀØ×Û‹›`ì²8¨’I«iÚ:‘¹_1á­Í­¾ý°ñjèdZ"¤®šHg¬ÐzÑ¡çÐÛIµ¼·;?ŸÃ ˆÑÓŠ: ÀU€Ôb@nëÆÇß°Âß ×eRÁ$Ù¦rÕÕV¬‹®8Öü7ïkáÄ ÊÑSÒ¼tsÔ*¢Jà,9·òÞäØÛ‘€¥m úYƒHÔÐ%#K‰>…ºˆ7°î9Â|Ï/54SÑ=c»HƒP€èƒ"¾ƒcµ´·mÎ-Ù•-NgMZñK)ꔨx­Å€^ÝØM±&g“üBd³åQHÍ“RÔ–ü+-¤RÁ. µZ÷Ü®öØ€§nàÊT£>™Í‰§P² T(;½½»b\‚Ÿ3˨ڻ8øùêŠ4°Qƒ§I7mÙ$O$Ûl]<²Œ[lŠmœ¿)ʳX¼$Õy¤mCUšT´tTßY„qY^R>@5ÖÛÝn ŽÕðÙ3ÓeU©_—E×ÕcWOMü€¶–'­ÉóœÎz¼=]Y5%CRB^0”㦳êÕvRnmÉ*qSͪ£Eu¨šºZJ… ¦_ÍÔ,,§˜¢‚6'Üâœs”–æÄ„mX‡Ãy¼ –T=e|U’<‰p¡H[ƒ #{8£Z̪ˆåRåµñ‡‚©ÐDõ*¬¾BA<ùdu /akãŸç^ƒ(¡©¬£ª\º\È<€±a:éÒ [–Ô×X•ôÃ=Ì«f>t’AYM¤,“±G@ÀbâÒ+!¹µôß{cBjJÉ>8ƒÁµþI%’«ã༲OÇTŒ®ÊQAþoçÜv¶å™©?IJ|³­§¥”ìXÿ5¹¹Ûµ½qÑ)h —ÃP|sõégŒS´ÐHHö*EÇ®÷¶)þ3àßÕx{6wª£rjhjjêÀNÄÜ|ë¸#Þø ½Å{ äÉóIêV¾ŠYij!OÍ…¾W· {ÛПåúánsI4…ª…:´M"‡Ó}Q°;ŽÃŽ1רéV°´ùq3®¸Õ’Ä)é·sÏöÚØE˜ÐÐjyÕ 8w),V6€&þ¸Ø“÷)”iœú*z¸ké$ˆÃ/æ"‚T+Λì½½xǹÕut1Ùc˜¸rt8¸Üÿˆn ¶°Ã?N´O UP¬qÎLqOº,¨n5v B‹{yŒÜ¢µ.‰Ô&E#X[GnOëC)ì‹—°6ñ`³ÕVfm–ÒVÈVY%U–>§Ê¦MÔXî¯sØý°ƒñEDuÌPG ‰'™eÿˆ7Úüóßß Ò¤¾5¦i@µ<’ÔÊá#¸?kÛõÇ6ñµ%nrõù5–y…L2ZHÕó¯qs`{öÇG)eÏ)7ÁÎÑÎO,ß§' Î)æYja¨Ó õ¯"žUoa¿Üc#–ž¡+Ó$>­DnŽ×ô6®Ü’ σŒîy£©Žµ¦]ØT€EÁÞú¤)"ìÊK(×ÒØì®³^à·*BôË´²²¸ìï¶þøeYPeb:æ]1-p4óû.ЃO!–W˜\ùd–Sc¿6¶ÇŒ:‚:zXÌ•²I$êL}ûÿ5ïsæ}ý0³»AO†-®§¦TZy ‘JXÕV±‚n8°µÅö'èJ`ó1´G,¡Ò”ù7;CÍðZ-)Œª]µ¢‹Ï)bÊ¡¥ÆÄ`!4rÔÚË ¢ËºêæçÛw¢"d‰ J 󨱒N”4Øþ/-¸õ3,¬JÚ*µž®ÄÊЬsgxÍ‹väŸÛ­¢ËgÊZ(ê#Ò@“²°&ã{£ôÄôT±£"å°–@Ê®G ¨ÞKÞÝí}°-Œ¨n–YUMO,J%Ø·”‘rm‹ýp>|‘CE23 V-ëý`;~ƒJ¦¢–U„B9ÌË¢R ]¯sÍ·¢ßLn¹ä”ËOL´qUR+3Ç ¶²»¶’ã‹}íÎO²ÕïXÄ-!Œ)[½‰¿#m±½L”Ö‰¨ê5ͽˆ$pO{qq‚3*pf–9ŧ[¼HÏÂ1$®ÛÜo±Âú¥q/V8íÓEE!n, B1mª ÀMO%2ÆÑ¬îÀ¤Ä’6Ô'êq-/À|$³T¬ƨÐÿÓ'‹}y·¾3+ –¢0+Z'Q¥‰±î9#o\™iªXÄ= DÐom;s¿s¸ÄRˆÍpA/^ñªÄ,>€ðA=û[× çŠªj+-®’&»Þß[aÜ“,QE ;Ë##^ò]Gókí¸±ß{ñ„Ó‰V®jŠxuÁ))¤žàÅÎû oÛУܽé˜)’T]µ2«i™¶eíúƒŒÂASQ|r¡Hº nú$A{mëŒÄrcïhKÊÕ±ò‹_þq«(ÖÄ0@%É÷IJtQÜèI 6 tŽënoê=ˆÆ¦12©ÒYnÞÛïƒwÁqàafѨZÂöcÍ *=µÖ}ûñ³³ M¥Ž£¨jS{öÖ5g•›Y Iõn-éÀÁª¨S"«+ß[ÙG$wÃJ>´ŠóÏ¥c󼓵…° mñ-PÅÀ-†ýÑ¡êHºH¢Ãͨ}~÷ÀJÁl,É$RÍR’Kʲ-Á`ÑÉQEKfUW6¶£¿;°ÿcTRËR]`óME¾‘{oúáŽd•0eÔÝ"±Èñˆa`t°vp/è-ï놪 ìÌ’yé´MFTTÈT¡[‡Rn}{ó‡•zÕ¦šF©…%–)7Eˆ»”X(ûàÂf£¥9VSG”Fcj¶±ab—P{ > á5%%DyµP‰§ÒBiä¾Ä5ŠßÝBŒ2÷@h—øƒÖËIENÑË$ÃQ²(bÍßs¾&ÍR¾jØ©#ÍRZ UUù,¨ÎH(>P¿8“Å®²šz,½Œ"e´E´ô÷"8ÉãUÎßka~Cæ¾®ŽŽtªJ©ÅÓ¸‘s¥»bXbü0 xs*¼ò¶£«5ă;J<ÄܯÔâÙU-ã™h`2©Ìih†š} ½Ï=¸À O—äEÖ£‹.hcÖt·æ8ÿ5‰£òšº[444îRÿ0Ët¶ÖÒ ¹ý±Nl»xFŒXw?ˆ£(zxô,p>L—¸$“½÷ÞÆüm‹o€òáBŸ™PÇf;Ç+` ò¨ª ÛÖÜŒ) ¢¦þ#MO²ôà_4Ͻ{^Äú[Ÿq‹”UÔµR$Ô´LÂ=ˆ@jAÇéýqΔœŸfÅŽ1iEËlÍ 4bZx‡QL“1Te<|¥t‹l·Æµ©i¢…‹3«¶¦I ¨Þ÷éß¾å°Ï[A::0©‡e´µìCX¶øÖµ©á),Q¢=‡QÃ#}{¦3Ï.ÞPÃl‚ (‘$¤jã-銃ÿXØ]¯M†ÃMJ¹LpÏ=4lùj\¨Q¶-ϧÛsjœÑ£X §ãT@Å/ÁÕ{ÛQÓg•N ¨J5qF¦z…’ѪÇî«v$ߋ۹õÂù|3á: ÏN+yP”– âè, ê½‚“ÞöûŠ,߆ÓÒx¡«ò&‡R j!©s$E[o;óªÀ“íkbý•øVžL‚§0Ì3ÚÊö dŽJRöÜÆ‘¶Öçw&Rœ£ô!¢ð,9&WUUÕu€cYtɪˆgóp;_ø2ž¼Ôÿ£…ic #†Á!Šû»·$ÛHQß¿ çôPF2ú‰+¦ÿ¦“ ="Ëó*ßµøÚ×ÂïÕåž"¢•£Ÿ/eŒÓ€Wf±[.÷ç¢2“l°e>É!™³x zz—R½WÙT^ûú~ØÄL_—d¬„z@q$v¸);zbµ–RÏ[“VÉün­ƒ†H ê£ÞÀùQwô'ÛžöÆÞÊf‹ ­Ëjhó!%„‹RL®äÞâ;Xƒ~\ì8í‹qÂ2ù§º òX¾>?äRÒMá|ÖŠvWŒ|e?L)•Á ‚wr)^ðŠü!“ÕÉÑæ}xÊ Ñ«Ä׃¹k²Øí‹oáa–ѪÕÍ[M ¢ ‰Y‰(±bwbÖ· a|^ªc•áéÃ"£‹2êÛýq¥â}™V_Jõ>`˧ÏÏâ%DòÐÓ&[JU¥3( ¢6çe 5É펒iÒ†¶g¨ †Wª£ë„ËçR,A[’œ\a}Î<ʼ+[Mø—šIK5¹téÕÒIè›Z¬7'F;Ž ±í„?‰ù¾oÿ®Z/ÅPFINõf ¤¤RMhͲä&÷Ó½…Û 6i·¾æì­øÊZ¬Û?’º†¢nŒ,i‰™#:C‹p5$ñϦ)yõ>qñ2DkeZ"|öƒ€CZÇÆÈó?ÔFPU)¹öÅŠ“,Ëë#†Y¤§—-™RÝH‹þ¤n{cN,Oiöu´¸Ô1(®NwáÊŠ\¢hÇÀËVCydFªçn9&äàSTfÙt’A•fôÊ fAsÈQ×< tæÊ²\²’¦Þ¢j†:…KȾS½ˆúq„>,’ª–š5®­ ŽÈË¡fN;›ƒq¹·‹*Ÿ ô YqæmGÓ†qzì²®<žz”š”j+2‹Jö![‹‘s¹Ç™] "¢—8£¦YIˆÏ!fkrGr4Ø >übÇå1×M[ZðU¿U´jÉ` ÊÜúmÆSå²Õ~øƒÅ9ÅCM6[V™f_$zIžY´†BÉ©7?̧½Æ4â“|12TyAYOZJTŽªžAANÝ3ÑRÞfòà°·qßêËÖªz̾šžk‹™¥caºØw€q|P)ç«§CCD­$bpÆ5 N‚,Y¯üàƒ¿¶.S³À(â§Jjt˜tŒ‘ ¬’,=ÉS©¾¸¹¤º;dLdZ‘DiVyF—„¢ß@ùXŽMÉö8g”2먪Ý&ajWgxñõNÖBy`n6ôÂhòég¯/§—®#XB3ùK07¬/bGÚø´ Ñe”Ô035Fa$ê%9)Ô®„¿#{’{ñm†2êµ0Ã_Äý zÝJÉۡ¯†ë©èRŽŽS^wW]tÁš÷ósˆsÌŸø‡ž«,ñ ϺúúÍb¢”)‰­ky…탪aÊçñ@ƒ3øU¦§X¢EÔD¥Ÿ–ÜX˜÷ão\0ñ†]$^øXR91jE•Kúعÿ.&žK:k²6E8Ë·OñÉVrI©åþ3;Ä dF¬îXÎI\Þݰ枦¦j±UU$5R‡†#NÈ%€v°S]΋_“*’oXÌL*Ä­r;°o°¶&¨›2¢ðõCAP‚¥5µ;É>¾¤§å%šÖ{ÇlLÚÇõttµË…÷n…§Žiª)ê3òŠ:$œ/JšºÒjÙ¬NǵÇ$_Úèü]YA’×KS=.o™Já]é¡!• ³¶¥¹Ò ¸ÛÍcþ²ð$~9e¨—6®¡£ŽsÕó’¡eÛm@j(A‘ÍŸÄ®_âž±Ž,Âò´E «ˆõ€ }D7±'IÔÖ>˜º1Ù}RT…ô™7„óêJz4ÊÒl®°‰å=p¦1$vWa{«\F j9žøÓÂþ—+Ë—%Ïê¡Î%‰D´ì𢙣ŽÌL— Ùxµ€½±,°ç™Å¹6{AiY,pÓUê꤄° ä$ƒ{\l4œ>‚ƒÄ¾Ëê&ªø¬ú¢•U£–8´HBì«e¹Úäâô•M"oÔÅK–V@¹ƒÏ%‰16˜˜÷ÐÛbI¶Ö]ø‰AW˜xR*ì–š®ŠA&)iìƒÜ|>SüQs(#Ž’ºU0TÇ'óØyoý/í†9ŠJ”j©¡ ±ê]wtÿ¾Öű“i ’<‘PM•WS2µ*Éýh°,¦Ö'±ކà "£È[(z˜²Há$Fë3²‘{0'Ö÷¶ÓÓQ”5ÔQ²ÉZ3æòµ6û¨ûaöt>)¨T`ž™ŠÖþƒwÅuÓŒœbø8Í^E9Fƒ›x[­$Ùýy*$ZhèÕ˜|Ï3Ý€ÿÅ7·ø±UüQ–: ‚®8ó“SẌÉr5îTnì=xÅ×ÃqMáø'œˆÚj¹+‘ÃXêò×ÚÄùãñÇÄU‡ˆ$zVN­¢­!›íØ‹¯¥·Æ¿ ƒþ3õfv`úœæ¾)u¤ãJsÓu`Ûm¦ÖäX6ãÒ…ê|AÒà£G}dMîEÅn0"WAQ5J zÄkÒìXØìǸ›áœÎ5©»HHòÍíÏ; ±ÛrF– A k54µ¬X‚Ô“p¼“þýp] 1ž¢9ãi²Û·ßs´Ÿ—Òd“g:»óßœK ®ŒÄk¾‚• ûþ¸®Ÿ b×±ä4TÐʉ-ГÓG¹* Ÿ×ŒG.Q8¬0¦™ä…D'å¶ãcq¿ÞØ¥5D®‡Ri u-ØsÛÔì1>_$⥵±R²ûؽ·Â{¢Èíí‘fðCÒ…V^ŒÅÉ–× ›a·?Bq ³ÐÑÓCMUP³’ÂhÜ †ä<‹à꺞²&¢ä°,Q£· O©7ÿBp4æ9Äj ‹¥nt ´·¥¸ç â‡b|ØV[’ÀVÐL+‘d¾ êmGn (íTuÂÑÔIh¸#I÷°Û·×¤“F“T1L‘’@|ºˆïmCÓŒQ=4s¯Ä ÔÃÄnuA°ÜlA¸#Ø`òнtÄ™âx@iMõ, ˜ÈÕ§Iú¤÷Ò$”Ízþ€v@Ò6»)'b>ÂÂØabT¬¤ ,le#æÞ×÷o°µÅŽøÊZ•jš†7«ÏMQ9ŽIM­xïÏs¿a÷ÁmÁ ù‰.Ai…ZÓ‰c‡S‘qÒ>CaÅŽü[@+™’ŽjfÝ•‘cÉ6ˆs‹QáI S×ç1Ųè†:ÈžOÌÕ •Ûeí~.m|OCÅEZ>"*š,Ò¢55=dº–­8ò7 v<‚/mÆJ“²·™{•JªÝê ŠL¢ª™¥%â`\ ‰‚ux¶ñM¡ã¥øÈJ%?j…O1!MìlH^üâÃâŒË<¦¥" Ý J@=6sJæTÜÛcqÛsÀ¶9ä4tÒÖ´sf1$÷Ò†xKz ‹Ûùyõ¸³µc'¹¦ƒ²Ü½*ª™+(£.”-(@ÈQ{‘¹þaŒÀõ™lAŠHžÊÍ€Ž˜¹ÖºÜ ØvÆbí¥©7ÐT©!R2ÊÉp@ÜoÛê?_\xÊbUus¥ÍÉö7µøØa“,€ª«žm­{íÍÿli-2éU0±Sù€.êØOµÉu L‹¾²ª €ê·;vDzO¨î6a¤Ûp,?¾Ÿ/ŸCH©*¢ ,8$ú}­#£hB¼‹¤sa¨·©˜–ýB£DÑSé sk°ã¶'¥/6˜éßSÀQ}Ç8ÚY¡U*°UIU$HzÓFN”—:¹&݈ãù-4”B¬Uæ7¦y<Š{X¸Û¾Ö¹Ëë I+3nCX›žÀ{ÛôÁ†Ér\³%Â*¾ †Ë~¦®XÕ¤e”Lör×ìn.,Mí‹tU"åÚ¡hé‹XHÑŧXæ+sé±ÂÀñJÒÒÉ,I*µ›arøÁtó/ÀQÒ¾s¥šôãs¤ÎÞ¸ççO¤kÂ÷ Ùîv‚·%ª¢¥¦–C’U;‰T)±"56×¶¦l%*?‹ÔÇ>aK[3´,âQ&“¦ä Û\tßÃé ‹Â‘ÕÆ§¦:Òµ†æÎ×þ˜åð¾c[AÂ*EiêŠàî{sŒk"É®C¢Í,¹eô¸Òf¹|×§’ž‹®¦ñ‘+$‚Ç€G8 ¾†¦£0dC}OÔü‰Ë›{úlI$•] ×1Ëh€@«LePíq³†æø'3¦ÍòšþZ‘FÃI”FK\‹\ ÷ ñ86&Ÿ ·ÃTÕ&Š®©êRäõFöæÀßËϦ+™·ƒ©(&’«/ÍÚyKu'èÕ–k| 3(÷ ¹<¦74ùí%E:fÔ1¼÷iØÀÒ'þL ›oÆxŽ—Ä0ED‹W TBx§ZJ ©1Ù€g?1çkÛaŰñÝt$©–ð¹„YDÏ=Jш£yZÌHmV:@Ûe$í{ê÷Ç39n{t³-;Î$ÉPkI`¤ ßMÂùG Xâç”ø®¯ ¢Ít×fµà=X‰Y £Œ7äÃ{nXÆàw>cÛ{fe—¦c;DÊ#Hñ¨y4 ä³^à mÛŽØv²G¢¸ÍK†(UŸÅ9ÈCÊëW­,³µšÝØ‹‹lÄmË—ä MÂÑÁNÇâ*.BÉ}§sɹïc‚s¨ü5—A–UæJÓÕ–)OLžjƒk%nT îEË †,> ¯ ‘J´©¡tÚv¹ n…À;úŒ<o’¬’Qç?…Y?ˆW5®¨šÖYžÿ=A)Ò;ˆ€^âÖ¹þ˜êÞȲú8êz–êy¤«m˜éáA±ï±ÅcÇ5teoMVhªUZW^0H\.›±±°oŽsø/™æ¹¯ˆþ38ñ>cÐ>[LÂ3PâÆä ô‹Ø¹·-`@× »f<ùZ§@üZñ_‡(Ö/ e”‚¹¤éÓÝDQ—m€ÕÈ-ÅÔ}ûb_Á<ò ê§3zXb¨èôãªÌ–™£ @ª é¸$ðFÂø´WäÑæÕ”“æY \!ºq£)A{rÁ-}½nûvå^ñfEà¿Ux_4¡ª Ž M)¨š¢z‡‘”»´J ]‡aaípĮ̙r6•tmø²3l—ñ2‚JL¶ˆP´o&_ðå¦J©4•üÖ´± ìov;v<ަ¦²‹¦ëO=6¨bÚäpt’·åM‰Õs{ƒÞøªxâ ÚÿøU)ro©f©”’ëvk0$°@</qv—Dšòä’Heé‰ãV]¹ ÅÉkß×:¤#~¢ÁCK“e“EµI,f}4êKtÖ䩵Ë3gmÍÈ¢øÖ®,·$ª†¡ÄuÖ¯xäoÊc§Bf¸@·^ú¨¿CÏa£zZ§3vˆÇ=D‰óiC«ö›cæ¯A˜x2¦ñu(‚µë¦z”ÍfÙx (m…ŽÛb¹ÔSêm!¥3æ#<ʨóJ=]+ΕIEƒ(%E¹;©Çb”L”4rTÆñH^˜²¹Ü¢|P3íG=§Ì&c+ ”üÀÖÒ¥Öö첬7Ûa‹ýty*DhÎðFXâà†ý1ãøÇ©Ï™1ÒáYÉÔê|÷û7ùU‘šäÝ4©ŽXç©Uˆ£h³4Ž›÷€¢áÕ,¼I”ÑÅ~y˜0&úcé®ÿÿ2ÿQ턞d®£¤šHV¦X›«XÉ=@η›­Úþ—Ãß Ig•±Ê·ž(#‘äÔ „ŒÅSbxê¿}ciuyaíl£6I.“t-üGÉëóßeBƒ0J)ãª&–.¢j- oRºŽäpqåeFUšUÐÒÎÐÁ =0%ÜØw>ApÃ{nG¦DíS4ˆI·T¶÷¿ï{}1ȳÿMlÙ›TT Š—Ö ÅÆÊר,-Æ:øusj»gCµRÍ~Ñ/5.+) 2Kyf¼2B,ÚH%KX؆½øôÅb§Ãé(Z©³Jƒ#&(‘c¾Ào!$’=6kálΧ=ð÷ñ  ’–^¼þ`ä(³z[ÍÛm­Šï|3>mI#Òæ2Ç.¢u5››Xîq‹ ¬¹WÌÑáÓ^nuÿèš§%z,Š»-§ÔÔG\°S­Œ‹fr\n™I°¶ê;a/ã5/†ÿü-áJz9*ÊùkªuXÈŸÎÛa,ªo~#öÅ“ðCÃTãÀsGUÏ$«›Õ¼« R8õXrŒ‘b÷çþ7TeÙ¶w.AY›,¥Té¨+8ÔKz ¿¨Æèjbò8Á’MgÍ'ÕœŽFj¡ ÒTÕÖ=(‘#”j°ÓÔ,lAXýñÐü!]5fT*ä ,Ñi"rçÊt!vÓ½Ï×ï|µ´?‡Þ8¦i™LJtééµd•Hf¯%·°'ŒT<.j)³•Êæ†Xcu"Dp5ì¬ûòǃÁí¾ØØ²)ð»CãÊ¥-´u ÙäÊÍGU%Yã2¨Ý܉ !Ü}ýŽ:…F£Ä£H\}Øÿ[žqÎ2iÄ544ŠÚ¦žµFUºÜÖ¹öîyÇE ¯j:|ß1tWz(Œp­¾vk[û’£ï9â‘ݮŸ³8þ5 ùñÁ•lÆxŠgì‹%Hi%hØÚ– áW݆•;Øm‹í\õþÊ&y#–¦²Ž95°²»´$†#ÜØã—Í”f5™7Áè³ Aê }lÀ-÷÷'O1’Ž ˆòúp‘ŠxD”è¼*'–À{鎾I8½KüQ¬0‚hä^ ?ˆ¹—ˆ*¤žWøùÑZÖE G7çS'Ë'¥ËÔSg,¦IšJÂw6Òµ¸Çúâ ꦕDu’ÕCOE*TG#3žíæ"÷ÚßCˆ¼_áŸýKYaª4©bZ&C}‚éÿ ±ÜásåRɇ»·÷/òlœÞGŠ?yZñãxš²…ÆMQĵ'¨ðÓÊ ¥¶Ð5ZÁy7äÞØcà™óŠt3*殨j’ É ÃÊ"ÆàÛ¿®*TõYC[7ò£0BïWFá×b@}ôìw÷Å¿ÃIOáj(å™'všI ‹&µ`d$}-oéŽ_üG›,4—ÓlÍâ²ò´êQ|(³z3e¤ž¢š’UA ¯Ó•`Hµ¿Ä1îWIšÉšRf2×ÑUÔE4åþEÐÄŸ{mþÁÁYW‡rÌÆ¾’|Ζ jAYJ–µ‘1¨ú\_ÓÂáx)²Ø]¦”<¦ëæ"û­‡c¦Ê~·Ç¡ðùOÈ„§ÛHÑ…îÄ›î‘d¨‚)¢SBZÕv7{±ç¾*~*X¢ž Ög.†4WÓäšÇcîTØ=0Ë'̨ãÊb.…$D‘–AÌäÏfþ`ãíé…™šÔIZ“3Æ” æ’Íÿ$}õ¾Ç~øê¼vVîìQⲺù5q#!´±Ž“s¸÷:¾‡Ûøb—2©Ë3|²¿]t(¢HHüÅ êßÜþ˜Ÿ9‰)sï!ºìÄ‹^ݵ Ôð1Z¢’FŠ*é)V¥¤Iõ­N‹uî-¼Š¶æý±ƒ>o*2’&|ž^'"ËQG•Э->½M4Œ :®à7?RIû UŽ*³,«ø5EK_]ŸˆŠp€5¼¤ƒÆÀ 4¬ñ-ø9£ËúµÕš¢XÍã…•Ø÷ùÉ¿}öÇ4¥i!ÏKÆì¦8ui½þã3Pç’kæyš”¥mwÉѳùá‡Á‰—PKtt”j•M ‹xÝÿÎl7f#ËcäoÄ9>dÔµðKçu×ÙÕÁ!H½­õ¹žû}⠤˿Z…à†¢©|Ê7 $Ф“*5€Õ§k†#b/Ÿ|-xz,ó*ªLΗ8ËÓ0Ëê /²0S$M¯ÌÅurÄ8Üg ŽÌ1‹àìâ·Š%M;,ÀÄáÑ€1Ëk¯¡ÁÑÕ»RXªÜꡱØð¾å)ÄM½ÀÍqm­÷e™åÎW—å5Ùž[=%s Ÿ.š`Íb¬@ç›r7±6ñe´û 5’ËÃDG¤|Ì×m7<L@Ù‹ÄEK¤ ÍpNÄX÷Æù…³ÂôT¹¿¼k[0’:Ü®šŠª’[µGNEp;0e7‚»sŠä••«•‹l\€.vÛß/ÃRdðçâ6V¥eð¿Ä %ÏäÕÀIûÇ 2̲‚¦‘…UM}3¡Ô =:9Óm$Íþ튷ԥ~ëò$c¹½]RÔEUš5[úü¤­ý,H¿¾5ˆg¹Ô£çre=ý/†ð?„(©'‡«›WÊ„œÅJ•Y‚ê{É;m{vÁT”™Zæq*ªëi«%e‘d§"ŒNÂÛ\ûbÄíô2ƒ=ȼ=šçrÑSÓô\ÊgŒ Ùúk.’\µìPÞÖ·8iâÏïøfxFk”OUN[O ©f*c½Å‡løKâÈ3:ª·*2-Ay$ŠFH޽!Aì¦Çî3C‘GD2¼Ò®ª·¤¡ã¦ªh ‰RífC»±µ¯`-a¾*k›Lx8.¹e>cšfˆ¹5ucAP©6¥Ñ+qrì6P|Çï‰i¥È ×9ž )$0.*œ\0V䇷Óg~2Ï|UKSE˜VS¤Ë¥¡G}¯·+µ­aýñZñ{¦UMMŽš˜‚àÄW\€±âö!HÞÛï{a'‡|{)ËÎ4މøKRåµÂ*ü‡¡Lу YŠæE,@bOøŽøCøÅ˜ÔÖxž<×3¤ª¥ |5r02"!ÜÞ×ó-Š^aš¾c4Ó|]U:T‚¯Ý(ØØÜ±ǃë°Áðç ¾ëĦ޼ û«H¢×Ü’¶c{m‹ž•ðÛáÿ·Zè²Ðf-˜kks(i#x¡“7Ž2òQµ¬xź‘1ÞàjüÖÒøæƒ5ðæG•ÿêSY%cê’£2KOKWŽ:+ ‹et²m™K6×bŸ›xªžªaYKM¾Q6SZt·6’™ÏÈêA ¾Ÿåc¨jXR\Å¥Ê\ºÅÌV¯/ª¢Š†zZµhÚPšúRu$—à!·ýÆbùŸ~eÑFž/ðtY ÕÕH*dó6$7÷ÇDÊr<œ/Çå¢y ‰4ê"5…×`A?|_ü-á7¢š:¬¶%£€ûI†B:ÛlU¯¨¯X|Z"Êò*è©£ñLú‹‚ÓhÌl7¹÷Úç¶+©I®Å¹=L¾"Ée× p§Q]'*ãa°@?­°ûðöy'­¨Ëó IêàŽNËr{o{qíƒ(|6S?\Ç.«žÈ˜)†Ö¿ÔbýECM_Å:B’2ð—¾þÝð#‰§ažN(†¢Ž¥c,4ðîV07°ì~ãï|qÿÏ f‰,÷‰ŒšUÍÎ) ývÇY̳‚iËC ,S~Z°ÞïoíÎ8¿_1‡9h£T”Ý^-€Û’ìNÖ¸?A{ª<‰Š-C˜ËœSÒ»QÏQ q<ÅQˆáÆ“û 2¨jÊøb¦©Ž%=O*Ñô½Î×Þø]–åt¹|rÓ§FE9‘fbnF“ô¨±dÙ}R;×ç”4³ZánŽÖé‘cõ'ûcªžçÁÑÓü ä[üMá\±ANéW}8Øy Émïk\ú⫝̸xoÆ9µ!)5===„…\mÞÀß$zH<ªˆ^™VE]F÷È'÷Åƾ\ã0M,°Ç ¤ËS,}Py]Z€ÛµíŒZxðÓ*ÑËù’kŽJŒÞ¨É¡‚óÄ5RüÎêˆZ2òßp?¸çô£†—%J¬ž«3«‡Kã#ºuá¹_Ó¶ LƒÄ.‘Ò"£å°Ž*Ž£=LV¶öÜIÉò°ûŒVóL‡Ç4™…?Âæ9Ä”’•J¨ÙmeÖpÀŒØp¿¨ÅÒƒ4F|ªeC9ÿÓã¾{S,ÕB@ž•™‚³¦àƒmírA'~غxV_0©*®¬Ì³9s4´ä‹ Ĩl¹KܤKCPfl¢_5k(•or\*4Øw t­,*ê, <²nxÔ7ÿ~ØATÔÙ·‰|;âl²qŠŸ55ÔÓe’ ®š˜ËJ§¦®½‰<ö8ã^8EËi)éd™^¡*kyÙ‹êE‘w>š‰~Û[ÉjaŽ âv—·ÌëcÏáq6u ›<É*Ò–xäxÀ:n6ßÓoÓ| QdsUEEÑ(I¥m7°$îvüvÀÞ¨þ'à<º¥è–¦o„$ ›=¶b/Íþ[ÿ˜âXdžH!–bÂB=%T)­ÿLs|AÁÎk›Oð9Ÿ‡â’äW %}¹JæÕ‘UÕš"³TFìáš3»n7 é…>Ys<Ã2Í~.* fi$b—®{€ÊíµÀÃÏÎÑä Z õ#üµ oùƒGìJŸ¶(ùfK]œÖE”SÔOðtÂ(UT¡ì×ó\‡­øÞøöê.*Óé~¥8s5‘l]–º³X¿Ãr@Õi @4Ñ·ý5$¼‹îpMaЦ¢««Q4Ò´4Õ2´¡WIcå‚串›_VûcIs*lºc”xvž&e’$Ì'e!ó)RîûŸ*íØ ±cðÒµ0”–yúÖ p€ v²Œ[J(s üú»2£øœ¾†‚ÿéõ[@iÆæ×çÔ‘Øà¿ÕÑÅàÉêÕ!§§Š‘fÐma)Ò#AêI%xܑߵUBå™õ^¤– Ó@&ÿ•!Rö±#Ø‚;bˆ–_2Ô3¤q•˜Z=L¡ZêBžHØp(Ôkc†PÇ·ÓŸ©ç’¤ãè•G+äðÃS[P¢4Y 3­§PeSby:H;ß~G;e¾}QNÔËšU½E2:éaL¨±Âíå[èqB”¥=m"µP¤šVŠxå¶µ?2w¸õúœYó c‹%éáPË(4…BànÖÍ¡WŽYõe:zP“¿qX¨Z,¿1ÌIÒ°G$¬Om wû[;ðìÙ•RŸ5Ó 3cƒ·¹pt¨Ø¶:oŠ£®ŸÀYÄYdTòÕÔS¼1¬ï¢?Ì: b{Äý°»#Èò<¾•)+iòá Q2£åÏ+cÜLw¼/ ž=æÿ{1ËæVÿ Îaáþu~küF¢:ʳA–ì«ÑFU¸½ì×ßÛŸø»2­ËalÜ &‰LÓê%ʼn:M¬wù·úc­lž(ç‡)h¡†YÈ©UmK4CkƒÆ0§ÃÞ¦È㫯‡)˪’'Zg’­5žžgH&À¯Üý±L2,RÍ)/T]‡:Û4¾h{ág‹ÃùlO¤É*É qùŽÏÏŸ;y8ñNwY }Y3i§§™Ø±é-‘ž,W¿¾;îk1¦£™‘BtéÎ…^…Ø8¶(¿‡hk|-.gZ¦Y §Y”%nÄ[¶çõÇàד&\Ÿ2x~O3$¦»8ö_â̧9ð‡ˆ(*('§9žmIB“ÒYã•¡LXÜð@ Šüo€2œ¾*G“æòÊÕÒÂéA.»,9€ÓÒì¬P8‰âáâ_Ñø{+ðÍ{»ÔÓ%E}U=dIW=@Hɰù™!…6çŒ\¼)øi—ø§Åô9íaÎ2l’°Çñ±ç˜¥¡þMÉ ßä=Î=gîÅ(ÂLuø}á8i|/EâZÇ©§Ì*ê$hÞ6F%cf6Ô [5ƒ ^ݰßÄ”ðxià©‘ÕÔˆ‹ årxußž=-Y÷ÁÇC%*EO¦PI*ð>› RsŠ5Ϊ~ºr”´È¥ÌÌÂå½­ý1ç²7›Æ.éLSyµ·'j(ßÃõ5uÙ}uL.ôО&zrUv"ÊÛ½½Í¯3ª)‡â4Y§^òP¢Ä!ht‚î×6ÝY…¹¹³Ò™>ã ækƲŽ¡8çÕžÏ_=Ìä¨Î(3hfÓm#Íwþ[R/{s¶:ø“ÔJ_Øé`ʵ¹ç9/†©zªÊüó.¨¦¤ŠJs2ÃQ3\²Ã=€âÄmsµÈÆx‚Z*ZZéjž•ZP JÇQP\€-Á¹8³øt=6Y$26·²ùím^P/o{_èF(SÐeYæw[šæÐ|%&J:}d˜¢JPùŒ{0®qÂ8òãË'Ô]”á’MoÿJ€«7ð§†<7K”fôYŒÙ]ME‡¦Y“¬¢æQpMÚê âÖž¤äÔ4•TKAQÖš'§Ö•ÅÀ ü×oƒk3Yë“.Ц *v)£i‰o/—k"éb;ê8Å’²–ikÇ¥Æ+y‡‡‡‰éråR馭ž’¾† nš(,ÞÚaûâË3éËW<βö¦p΋"T±:dIo¿¶.^Ž<Æ£)ÍëLÂeY¥§ª™$ ¥‘˜`VÓ°ï|tµ> ¥§ŽLO„ßäͺ‰c”!gñ†<{øñø[žOA]ä³Á M]Q¦©zY.N¤…‘€$—+ó8Âx~|ú˜nË*HË‚Yr»OƒÅX M[­ÔÔD¬Œ à(6 ?Ká¶WQ#P:Í–-^L’ K=‡@ògžÖÓïŽÍÿÿ†ù„üA•x‡' \§ÃóSŒ¶zZ(‚ªÎ¦éì5Ç{·ªMÎ8nv’UF‘ÓÖRËK¨Å"5AŽ{ƒÛ†c>µ;áz{þ©rLûÆÙ¦QKMG'Æd5ÐÌäå*Ú!Úå®~€ádñ#<Õ™ Š1$Ÿž˜ÂÒhüÙ6é’M…ù7µí?áBh×ñß!ŒNÌ~¨„t MÀ·m»úbÓAAK–þ þ2å’Ò _/ÏZ”3KO ±¼Q—úE‰÷aÔgŽõ.~t7›rEƒð'ȳïÃïæ9ÞS—6O[¯.d¥`¡‚3#º±ØyJ±Ø2cæœÒš§"ª¥Ë"®s,)Ô‘é\•bA·rµìÝù?Of4uü$G–åðÃEnW ÐM•~*@òI¾Èî9'lpÏ ~çYæe£ëO2­\”ÌòGL€¬Kfr§ùHÅ^¨z‰æ›u.>ˆ§§•¹z"»SSâ/ftrÍÉAL°D"‰#ie <¶ÔÇÐ Ÿ{âoå9žK_ZÕ0ÏUl*#tšuävâàùÎÖ ï¶;‡j(|´Ÿ†¾ ð¯ÇUåÉ^eœÑS*UJ˜,£xÙ”<Ã…Q¾(~ ð?‹3”Ë¢ƒ#ëCQ.¬Ò«_å‘rºõ1óäûúõ¡‘NÚTI)«Š9öH*'i~"ž¡tC­Ø)³ $m¸’~Ø—Ã2PTf´yuv{‹Ó4f HÚvMDÝ9ä\Ü[:§ðwÅÙeOUr솹„Eš¢ éX©$1tE:Ëc`¤úî,t4yui0Í3¼¦_ÖQ%4pÒC¦:x%´* ç`IcÈ ;a^X¾=FPÚrŒ×(ɼ;ñ¹]FW&]™ÐªÅWt¢©$³¸6[ZÖåK÷ã͘eu¹5]\•uei)X£D…”ê`,éÞ×Û}ï‹æAàÜú<Ís1˜d…éGQä’…'Yƒ.¥bYõ[p|À€qÔüEŸÐx>¤DÍ’ ’·ø}"¯ÄÙÊݬºØÛƒ½Åu˜ñÊ8¥þ¯Ð®rPkw©óçƒ<&+óŠx³ ŠzLŽ*¥züÊ6`Æ"nLjEÌæò€m킼Eøg5ñÑ$nÔ«S'Âü5WMé¢d™X³6ÿ(µöíŽÃø¯7¼;‘ÒþŠÊ ¢²H”ËZ´BCBšƒ,L/©Z[€YO”sÜãœæ†ywƒ£Š³4ñ],ed‡_á²þj4dyl«Þà-Ú÷ä iy·»C¦§öxD4~"©Ék¢“-˪[6Ÿ-Ijê¬Dä2èT`H¤Ü Ü‘µóÿôn[šxbLý¼QQMENZ¸ÇÑ€"Ĩ©©×ÎXÚT“sÀãŒ9¡’ÜÙ_—ŽŽ[œRMGQ,u3ÒÓÔ! GRÁ¯°½¯«ž}°VL³J9ž§1쥬D„ú/?p~Ø»UeuЬPF”/I ](Öª!#ª“s§Z’õ¸òI”0©Êiéª493£@Û|Ãa¡÷ܾçrv“3ü4¡–géÅPTFÆŽ$²0m% @‘~Âz红øs/Ç»APÊ$¶ÄCËÀâþزå>$¦©–’iÄY]UJ’‘»¹Ž72†#O Èç1䌸3|XßG9¤ð`&–9èNgGäXäºïuòôp ÓÂEœE*¹¨QÒÔ–d`. ?®Ä_ÅÆ“'ž³Q0eÊÓùVn¤nÀ_wB¡oclM[áò ÑW–ÕDµFgâäRÈ4¸òü¦ß1Üó‡òâßJj\¡vw—GžeÉ—ç°Fÿ!X$…TξÌÜÛŒUrï d±—Éëê&umh’‚D¶NÌ>ÜbþML¹¢A_•%E`R#jxÉrodíokÛæ)UF”Óæ9D®D¤Å­2ÜY¶ÚÄ{ae>†Y8ðÎGX™zäÏ5,“”§Sì¦ú•A°mÉ-nÇl>ðîG_@µñËJ®ÔõKE „g]Ù»VÞ„àßÓÐG˜­D0T#“uAPΨF÷`ÀiîvæûâÁâ*ÛSP…Œuf©,X-ÈŸ¢Üã™›&Üëí•ÿ÷m@4”Ô”¯xÓÅóæþ9fŠ•Z³A*> ½lïÅ#2ñ¶m`J¶H‘„t¨Ð³:-­óêžü{o…4Š[0ƒâiÍLMV&!Y”ë noȽ¨ÆmNEµí5iøM—joÅ“Í@ÙåUVSS ôÝêA‰]5zµƒ-˜ C½ý1c’ž ê¤#Ï4šKÈzq-€»’¡®îv87Å“ÿë òŠ]y•+ã]‚é°–2»Üi&ÃÔÜá-~u•åÕõ0fÍ[Ð=<*·TQ(`¬¥ù‰/ Ó¹Ç|yª/Ójc–à×(êTõTõ_‡5U(ãáúsy‹iUÈ¿šÖÜ Wòô™*)£ƒ: ml%W_4á * YX‹ß{ìF%ðÖ`¾)üÌæËËLj>6(ƒÝ®DŒ YyãŠUu]\t°Ð'Rµi,Óuád5µú~SªÇ°#å;ààO{bišnttºíš­-U¦"Uª–y»5ÕT(:¶ù¹ÛœKYK–K-såÕeŠ3J—VÞÚ@V7Üéä‹ón1Ãrú÷;˲UŸ­UE:*ÄòôéápÒcbÃR­üŒ8k’E±Ô¼Eð¹{垇'—0Érj_ˆ¬h¦XÈuFÐy¹½Àîã[ÚÄË‘oQHsS‘F”É\óäU²;êž‚‘´Œ¶’H"äˆãxlf¹ÕTkø„$ZIŒU LêÖà±PG#¶ÄskãÏ x¶y-E_`j…4”ϡٺŒûª/›››{í‹ ¸•¦b-k¶þ—ûáGáõEMfO]âZº?‡©Íóji¡bn±"t¢'ÓTq‡·bþ¸hdŠB²DÀ¯Ëqqb ŸB0e2½Un¾JjZslE¯#|ÚG  ñ¹·|cð­DòeÍË¢˜NRõä;(êrÊyä`Ìè `,¾Vf5”ÙŒ9 Dùp³Kž9 ¼vV›XmÁ½Áãå•rVd‘e1u¢F§Hž \1wµÂÛqe$êà¦<ðfKQ”ø)hÌLÚY/rNþäéV=îN:ø²I`„Ò¶Ò.Ç{#fÞʪ[]\òÇWKYıÝÙˆRÛðý6‹† <©(2;³X)$óo¦ÁLRÇH—Б…½÷Úß×|'™Å‡Ïµ½ñÇñܹcÊêÊóq\™•Ê¿1–G¹Þä“cíé‡ÎD)"‚­u³pþ+EO9BT¹¸™üEZ‹üj’J*Qa{Y©ì¶1nÖ»€= ãx¦RrÑ|ìM4«á2µ—xr«$ñ¶aGJÏK˜Æ&‰VäG &ö€­Ç¦üE?Šc~º2EFÁ€\±[qË=ûáÅ%|Y…4YŒ c`B[ì ½wç̼`!øúh–F6˜u'´l,>^~øÅªÓ`†v×|×ÜŸêW’÷S÷6É$ ™¢¾Ñƒ{ßA°ß×}ñÎrì®SC¡ghÝ(ÝÒè½Fg þ ~áGs‹ÖkV”UUPħáP°ÿâ0PìGÔ“†™Í6]\´ÌHÒÖÂ…iÈo!W*ÇPïm"Þ‡ïn~•¨ãšÝöûýŒZv–èß\‚R<9fG,0™RÀ)©!}Û§é]Çv6'×c‚éèÖкùäX”HokµÎ£ô»Û óC$9šÓ”eÕHõÒº­ûŒ2˜T Æ‚•Y”k–&V¶’έü£Ûœ>“ËŽO"åq÷Ù#)e””×Ëñ=¯¡šl–ª! Ó% ]†êG­ˆç¾'ʤ¢èÑ0ži–†¦¤€W­+?Q™‡›W•Eìl­acl_é$Y3ìèîɾ‘vL*ϲš Óç_ió:†¢YŠ´õAÐs}ï¼b÷HMŽØ³G(焤¸iq.Ã¥„-×§è“PeÙETp54iª6¼²YÊÚÊIúnE¶<âÅKG.¶t‚Pd1rÊA@úúóŠËI)®Å¥Ì%Žàµ»«“öÃì¶­ãRW}È#{gþ?¥YÔyÓøºøž£$’£±–LÀW; 0ío®ØW—RPøf¬å´ê“OΣQcoO׌›ÍS™*ÆÐƦ'G§rm{þ£lKáúx›,ZS˜´™¥| ]3DˆTÆ,8PHü^aŽ·†8åË“Ëé¥ÉfEå’‚áúƒçy…câZ¬¶–jŠcKDËÉ Æ@‚ü€»“ÇžÃ|-ñMoð ý¨äd­§†A—ue…\}w#fðæÆUsÍAð”QGR̬¿óܱØß˦Ö6ÁSÈ%…!êÌfö±¸ïúc‰â×-FKôegs’—eCðî›1¡ðtµëÕª¯q$èd_úÎiýOõÅ–‚ƒ=9fSKR]bÔ£WÈ„C¡‹/ذØ{)ü2J¿‡®Ì/*e‚¨SPDà€©*Î`Ïý¸»-c|<ÍT3ͧYä½¾ÇôÆ­µë_q4ø¡·âö*~,˳¿ÉK–Æe¼Éñ ÖPaF,äj"ü=qϲ¸ê寫¯¦¦¯ŒÉåø9j.‹á´¡Úþ„“¿ëpòM®ËCf:¬¶±ý†9®MM]GRôê!‰WáìÒ9!A. ¬n~/AàyÖ\iRLèè' pÚ—E+Á?Åãþ=GšÓšX™à’L:Wq }¬/ü¿¯±ÅÒ‚™_ÁÒe3<}P±U_üZKïf\“O>Jé¡WˆÙÖê •Á ˜ž00«Lî8òj„) ¥,±€¡YA-sÜ«liãkª‹!TêÉ-1žK5µ°`6?VzŒ/ð ;ÁUmKÊL7H‰ÝF I>¦Ü_ß ɦœV6î_‹ùpÏ&)Òõ/>¬ðæ}¯>Êé(>5JIæjeŽmq,·"ößkÃ|àÏÁà?Ñä”2,õžš[ÿÌUJ÷gk\س_½”[°Å[ð£Ãá_4Î*éRZy«z™RÔ i!`­“)#Ê$E¹òÜöÅæ)?ˆxÆp A”Àf“}Œòl¿pºþXöx¢£:CtçñlOýÅY £¦JE‘ædÔÆGÙ¤sËpI¹ûâåU§ÄÓÏ ùiE†[HŒ£t#ê¹ÿ Í¥ÿ˜ªž þ 4št°°M;2¸&øÚ—]ŠW©“åô,t­¿Aýqåpdòµ™²Çšáì9,Ò~à9½u <éLÎ’JUi£W²ïn›Å÷ðÜŒâ<ʶ¢(¥ie¥«VêÝ6W»!µÁ6}mÚØ¬~*WœˆäôÔt‰U˜æ“ `’©( LÌ×°P íµÏ|4ËczjJŸ2šV©ÌKÍ:‘Óekïv[ØvÓlz <œtÊQ~÷õ78å4ËiCœÕTeÙ>CJ*éd¤ŠV¦Šq.—böf¼nÚ›rMùÅðÄ5¹×†*e3A&]T ˆ„…â1££\zkeÿà «©¨2ï UÉe™l¹M3½bÔCÔ { ÁÛµ·¾+_†å±øƒ>¨É¥h«i)eqÅÓn­5ÓOþ <¸kÿ£IÝÓïêlÅ9K\ðE—å9}‰|QÑe4Ùl¨dyêéé˜Fß. mÕ±&ã›¶à9ð>W“#G/K+¥ŒEO®.—VÆÍ;óÿ”üØc %ŒÑSRÓH+%¯u…lIÓbO•Fý…°Î¡i©æ-UP‘à(Ô ƒÜº(]WæÀo¶&+Ô´ý»2yžt’¾…µVmŸf±F‡,£h£¥œ‹|CL„ŽF“eôçÓ jÏüî\‰.†gs§üJÇì.1ˆQâlT"ÞÆÿ׿8Äõ_‘ÔéS2Sµ<¹–fUP;v;®0GãÕKw ÐŽíÈCø’ÉV´UÐu5Àâ´4.G=­{ öÕ~8†£Ä³fù#ÒS¥ tpÁ¦¡™[Ö°Õ©Vý¿¦/Ù}SÓSѳ5CGÄîö³ØX’>ƒ¬ó#ðöAOœf•9U•ÓM,ïVéy|ò“¬–¸±qmˆ[Ûp1º á=ý:FÍ;Ç‚3]³šçôSÃKE\¢„xÇZޝO8° ¤ƒ¸ú›ã¡x2jjºÚºšZT§†Hc1Æ>X'R½ÿLWÒg¿‡¹–SI”É¥®Žx#Ô»2¾”6{_ar×¶,Ÿ†ES$a$Šhʉ¢poæÛûßÏÑÏK5·ì?C³I,96Áü,ñ?1«Ëé©i©j$ˆLN®™ ¶‘¨Eˆ÷çë‡> Érú ªsj:cù¼’Ô7VXÛÍn%‰$s}÷Â_ÄŠU¬¨$¨’e‰¡wXšCµõ ›ïÛÐaÿ†¦Š?åk—æG1S¬i*‚·`,<¬clUƒrÇ–-¾(ÓæŒwóêsÕðösãÚx+Æ™QÌò*¡ùñ$e´Ä·ìQ£BWc¦FõÇÉùð TrZ<±Ö|º˜S×”Œ—3)´…€â¾>ÿðßñY¨óJ…–4b*:V½´lØÜ’M½=±Tñ§áï…¦Y”ó ï¹ÃK$±b”¾Cj'(brH+ñŸÃôä´ÙV[GM8…Џ‹J+/mµYK~˜#ÅÕ’ÑUåÒE$ùsÔ¥DQæ-E׆œêBVE KXƒÖÄ(ÿˆ|³?¯¡ðŒÞ¬JY"ΣJ’μL `=~A·¾þ;äÕY“e•ú)é¡‚nµLèæN¸Êõ´‚Inos°ÇY\óa”ûø‘Çó<ÉÂSè/ðœyÊf³å9'…+hT£Uæ#à [‹kyBÆ7PH*˹ÜX¼É«2sèü#–eÔ^$§ª†¥d–,ùm<ÊA¢wÑ"\YŠ.¡q¤Þãâ³Ä9tT±åùõ\Þ$Ëè¦%&Y-L4sLåe²uU³\ö8¹å~?Ì3jùa¡oá2VµB¬ÔqÃ%Lr…´,ÿ©}^çRª‚#…c”-®Ž¢Ü£q\þ$~Ñx“*˳h2ñHÐ&a’­ix¡»€^,¢ö'KØé76 ˜‹(Ÿ0ͼs_žå™´¯CBƒâåxº-(w+¥£ÐXê× ‹öß1ÍÍŸdªN˜™8:“¦R╪]Lï´ìê“Í݉ú†óµ <3iêJ°"ˆuAóAØ{ñŠÇ‡h¼Fõó¼”4à*¼Ž“KTw, Ð]®l}ß :sP=fœË)ŽJšq§_ÊAá´µ¶°óKã¶¾.Ìh`•ÏñVÒ‘¡_+¤‹ÜØZÇ›ý1cU52šÂó¾±"CÔg^ ‹ÀŽäï{[d^¬Î³‡§ÿÔu‡4¯»RÒP<’õ’×ü‘ ¶«Ÿ¦-_ˆ‡õ~ŠJ”ÌÐe•+Óž¹êä–}_1YzbÃ{X›ì1T²Â2QO’™d©S*¾"Ìc”CES,241’ÖXä"×RØßžøq—~(ø¦y#øOeP+Ìð]¡ŽžPFåwß‘Ï èj2xs)c2Ó׫¸é˜cÊãÿÃu1 . × å ÉØs ‘%il„ AƒvŒ)°çQ%½q¯|’àGXDþ$ñæm”|-Wˆhêä’@ÑÀfŽÀ‰#+f{“bIãü1ZÇW.[&hõNbÓ¢hʹõ•`ü-éMK›Pç”fŸòÜEÒ1¢87E‘JòFÀòG©øz QäŸ Ká|ÚDžbTW‰dòÛÎÊG _×nØU<†Á¶%Ûðã8ϳÄ\šš¿5©hcëui¤«K˜Y†¸ÉÕn9ãø\ÞH<-Wታút5SÕFYU>U¹!˜ ŽþKá Ÿä’QäU”¹ª$Â*š–F(½)5  Ü“ØáßãÆw—åµÙM%qa!Ëå!Ö©`,YH;éãR1Íøž½G×i’Q_Ä´½Š‹¼’ø[;§¡ðÝ-C¶iI-sMR“ÆÁ`RŸËdR×Mµ‰ÛvÊóÈåH3ïæùVµ-ù=BÅNƒimÒ ¡ˆÓbËÇì!ªÈ*?¼!YYF¹„R@·lvúŸ æy6CS_—xt$µr¬M>C<•‘D§Mµ5Ô‚ºµ5Á±°·¬fµ¹ vo$Y¦Xiꢓ ýva4h„v ¸±¸c>S.‹I÷ÁOüË*<_ã ͙ÕÔCBÕ’Ïü*šq!•BÀØþeÈ;ÜbÕø±àjŸe¹/ˆdñæá«%FºH©Æ¶»#*FÁÁÞä•=Ž~I’ŸÅŠhòì¸A3RTS‡j¢Ik$!îÛú^²3OÃeü&ÍrÉsH¥—/JÊ—ž$é¬aÞI@î5Zþ£ó,Ìj¼E$mñ•ŸÃ¦ƒ¥Ó³‹’NÂãYÀ‘¿Í¾:wŒ#–«Áž(…QXË•Í`O6CûcždËUN’P²²š¢9’:eyD±”܄٠`E¹Ókó…ÐåzœRÉjÐfR„¦øÿq¯á‡†h<9U›ø¶¾’mª‹G%[†c.’ƒ1ÕüößL.q_Ù…Lóæ)I&ePO,æJU+ «!ó•¾ÃP&Är<¦åã )2ÏÐä9ÉièéQ~:¦m?vk°½Í…8­øf¶”æç9hÕT£/•f¤¨DJt‹§’ö v“kéÆÈ·._¡f*œÞDA•ø§<ž¾Ž¾Z¦tœÄÒÀ¯ 1;ù#B  }#P ß(±åÞ"úŸ$&àž¢V¦’8™Æµe°”…ÕKß{‹8¸çuù .`”ôÙí,ÙβiÊÂÝ$X¥µ|§¶“ë†9…üC˜µU.S-55V\DVg¥ByHu=@t›ÞÖØv¾¢5‰¹:P㱫;æ^^7š4DÂáM†Äß{bYieC-sÍ0Ã¥EÄLd±P6?}·Äyqœ˜f«HàšXѤ‡¨£..66&×ÇϹ‡â5G…üY›åY‡Š³É¿‡ÔH’!Ê40Уau#a½·Ç?Âç<{ ¹JÎ~’.1¯c´§ƒ«²ÊÌ´åõíWG Ô¶«kÔ2È ¬´‡±Óa†¾¤©FdáLŸÑR¼{°·Ô¥±R˼L¾JW™SçÒ´T¯LTkv•d;*¡ÚÝÂ÷8sâ_Px*<°f´“­ \­NÒš„ ¶’ËÉ M¶r1|µ1É©ŒÚ«‹‹x“Ëß Îv*YNÝîpÊ ÒhbnÂþã æ–›âç¡Vÿš TõFº‚>êÙÁ4·4iê.1ç!«Ë‹4å-"Œ-Æ[~G™„ ™ ¾¤*¤‹ÜÜ#ƒN6õÃ!2üDt„)^Û ïícúá6Kñ‘çUS<±ü Ó"B‚C«¯ªBįÒW|E˜LÿiØ•R–, ãëõ·ëŽÔ|[—O†MÝ.@²¼xácLÆzš˜f¦ -GR’¬-#¥ì 6=÷±ÛûáfY_m•ÒæTÿô§QJ•e%XXî,AÛÍW\a¥¼ ÓÅ5匛u¢¡q{ áŽý‡®åQSR@hã*%–If°]:–úu[±$}ÉõÇSÇ0¬ºK^…ù–ìjc M/S2Ù¡'b0}$¬r¸S¦²u‰ƒ[N’|Üóµþø[–0ØXÙ?kÿa‚(g•㎂d‘"39öó+¾ÛÙøô÷âx,¿›ýT¿¿Ë*ÓI7ýÿ@/PPPåÒ.YpÁQ,•K`ª FãJÿ.Àl6¹8¯xz¦9|WðÐBõ-F³üKÇwTù‚žOœÚ݉'|]•?:mEUoÀÅ^ž‚¢›Å²W‰PÅÍ¿êT»ÚÇ:ó2,•îW(s¸ó7…¥Ÿ¥RóDP+’‹6bn=p/†)ò:h¡w¯ZV©*Ÿ9¿•Iä(=ì0Û5¡ª‘àªHÔÃ3u€jïÇêðå/𼺒(c¦†áF½ŽÂ× û=ز8J/–Œ‹S\0zƒÖÎó*û xœ­+1Ù¤ ¸±ï¦0~ø‡ÂTò¢µ\³K_LÌýid@–}6spÖý"þQšø…Vž™´e£«gØK-´³ú‘®?îõsã ’¸Å‘®_õ–ºœÔÙTSPÝI¹Ýîmþè1é!§ó1ä”W«fÌxe'&ø7©ÑüXÕ µŒ€ñrý?|W&c–M–I"©©F ª=zXî¦Þ«±À•M#eV(D²¸m¶ÞØ‹â#«¡^Ey&#ÕSÿŒyì9T'%Ûoó2ù»27Ç=etUyE%=erVÍ (¯R‘”êéÛV›ì.Eð~TªÔ)õäbH6R[V‘ô "¨òxfƒ<¨MÃ*ÌÙ£v:6ìnéïë¶'¥¢¬ ª¨JÊÊWy$Õ=:±®ä¹¿ó;]¥ì8Å™4o)Êkºkï p8|}'úžÃ2.h‘«"hcqµ‹[žoõÓÂ^­Ê)eoá´šýDÂü™¶ýQ½EQfL7iNÑí`Xý ˆ'ë|=D"ÊrñWR()as®ä‹o½<ûz`Üü•Ì€5Jù‹ •‚¤úŽ!øV¥|¦‚Šs£ât37ó.‡r6÷¥ñÎÉ‹ÌÔJ1ånÿ4ÁG$¾_åø’š–›:Ës:ö’œÄ¸XЫ³nou}J/¶+ÑEKUR¾„Íð“¤Ò»^ÒYF•wùÇþ# ?jh ÊòúŠÊežz:£-20Ñ.†PÚTv’ ð³!ðýfW™ä™¤Õ!ä«Ã$&1xÀ†F‘®=_|mͨóV(àôù~ÿ1u_HÆ>²ïNc¤UT$±ÞÀØ`?N)|7›çÕWI%Ï}¦ß¦ãøŽ¥b¢†‚6j½R0uEþ×°ÃI ‚—ðþª*ˆíÑÉÕ@w:ÁÔ?{c¥¦–ìîMð¢ß÷ÿáV¿3ŸE¿¸­åhr¿®úêž™d“©ËHËrOÜœD+³h¨²ÒÒåÉža–hÜí2©^²F?Ç iÛ½í†A£@aÓ+¡¿$l}1½‡òڿ㙥TÙ§N ihدK©}FR©·°·ÛsÁô³ÏšRO„Ã¥•µÒfÔYUxƒ4¯[SÓÿÌBæ3«t 6¿‹v˜S$ùmFcCK‚ÄÏQðáƒÈ×FReÿÌ×7Û` ½Á¯ÌóJ ‡ÍŒTÁY*^5°11ºíØ%os}7¹çÏÂ\š²ø“3Ìë饞Y +IÔV ì©)~ÅÂ|£Í±è!›#<yÔSU'ý‹–pžX+•t™“ϵ¹;úâ™øù“PÐf‹á)$iL]ÎÓm ê'‹jîHߌtªºežyiUGQ)î€Ü+1ÿ7#{vÅS7Ëåž‚®Ž£É(ˆÄÌ7±¶Ì=mÏé?©Ã›OŸv>¸ÿ'Q âɾ>¿¶ ”fsfY[žtzsÙˆÓo3#$[` ¸í{c\Ã8¼]—,žd3E+,ïvgûñ†tÙaÉüá¼µ‚š¨©M£‚åHßBç÷Âlæ ¸Ð>[ /ÇȦz™£iœî’‹ÿ…¼ÀXÜó¶(É ˜úûަ]R†=±xžUŠŽ¢y3$Ë¢‰ËPÆÀÈÛrO`78ªAœO˜åu9„æ«‚u•ó* 5°d:qî06ÔN¡¿Ø´øâ’®¯/¨¢Ê Š¢¶¡?åWÒNT“c° _ ¼'QáôËÿ7$UŒÊ¦%aÓ¬YTª‚Æà’~ƒ'†-¸§}î*ðüpøå/F\hƒµsÆàí4£½È0¾äØ ù<K¨Ä~©y"ж¸täxúò®×ù­·× al¾*¹dHäêÕ$—`G `ÒÊ)Jr’æAÃ4ÓiöÉaFø§¬’F°¤‰À$I÷áGØâø©Dùׂ3|»§<“U¢B©³3;H¶PHïÛLñª*sïÏ è¥†¢qQˆhK¡ÿËÓL02­¯¨ƒqß× Ÿ,Tá Ö“+Í5qiñe ð5ð¿‡óÜÓÂYUe[H&0Âjу™e@Ì $ çùqŽ™0©¨-5S†™‡óAý>}ÈÿåyUtSËYY›IœN´‰"…Ó2ÈKJßEÉbx%qßc­5Ô´•Tò¡30F1‹CÔ]â¹å=¹W1ö5ê²G2Þº)¿ˆðT­P©¦/$Ý;ÝÆúw¶›V7¿_øc™ÖçÌVºªZ§ƒ5juY]µiX£:.|Ã{ûàLËÅñÕfùí5e³¥tòt«ºÑˆ¦²Hœ¬l&×Ü­ï¿ÉV^ž8Þ\êPÝ;”f駘m¶ÞÖØcˆà–¼vžÓ“›MäÊUÓçû—¯f9~XÙtæ_‘®ŠÅ£FwóÆàk!€áÍÅøÄ™Ëå®Zâɤ²šTÜêQÛk\úáánZÙnW›=MLRVÚ9æbڂܬÂåAؑ鵰~eNž Ës|®:Å¥yuS-@º2iXúÙˆ¿Ó ©ÖMk`¤iÏ“$W¨»/†Vð¾s›g2ÑTÏ_:ÐQM—He(ÚDE ‹»1eƒ}†x–¬¿ˆ2Úw:¡Ñ+Ù›`À®ŸÛPÿc&E5†² ”OM,”C%kÅN9]˜ªöìmŠç‹«óüRÊr¸©²Ö£)$íLJ,û²¯S€Jö¿¦Ä2KQº7ÒfmJœ®+¥E«&i©òšhz"Æ¥Pì9ö¶=Ì“.cOYTª¹„ŒÐÓ9-c±b·àϦ'¦…éÑ ’>›Z—Ð’IÆ54æ)ÒVéÏ©Ò 1uk®ç·7ö'瑬ßᮾfxMôýBbað•qÊÁÄÁ˦ “È?0öÅ;2ü8‡"˲\ÇÃ9&{= 4Táë^ÒÇ ®ÁPR,@mõiy¬-r#TåµÔÀÒBéqȺ‘úàÌ·á(3 §Å-,’3(¹P›Øs`=qØð_“íôt4·…*We''ñUy‘ÿ£Ëš—3ZXÖ(—C* +`T€ ùŽÃp; ±wË3Ü·2¦«Êèê)^j2:ⲩaªÄp¦ç‹ßÃx)Z‚U§…%Yrâ¶jXâ1Ì.(R䮯þ¶O0 ¦§¢…!§•^I’8º~bùÜ#ýF;Ín/*xeö/Ôêk5IÅÁöW¿#¯_ǯ˚d©¡Ì¨æ¼BçA#nÇm.OÛÏdùgˆ¼3]áúÈ•rúøZR?˜þaèÀîb/€ó,¦—Ä>ÌrZÛjàxØ‘}&×ìl~Øß)ªšJ8Cê/,zÔ;÷úœr0gÙ² w¸âÇ*Ž%^§ÈÕ>¦ð µ´~$ª0ŠTwZ:w˺°‘‚›2…ÞÚ½@Åg;ñLÕzT·…骅Â-.¹ÁŽ×ªÆK”ñ~GâŸeg5ª«_áõ4­¦…gYn¦àW ëeÅkðsÂtKŸ¼­’׿²Q@³e•³JñRüA]`6¶ÒÚ6:½îv¹¿©Ódóð©{},üØ®xGGÍii²/ÃÏ ªÒ¬¾i™ÌJÆQåDòH\êÓ§A¹Ü›ÜÞøÌMYQ•fƒ+ðNkš>oâŠwžjJÄ£1RÓ¨•º’é ÄGau rïŒÇœñloø–ýÌÚüqžfí#œÕFÐçÙ^A‘Ñ ºL·øu=E\hhäeuR©¤;omHE€^×8ï™ÇàÏ&ËÄIO5ņº¤pòIÉ7 ‹’NÊ1Íj)28¼]ái<-6c’ÒgÑSWSÕQõ$£˜È¢7RÚl.·YÍ”)Ç~Î%W‘!¾à_|wµZÕ¦ƒkäuuYü¿‹9VG“P~xë"£‘r“Gšõ¨éªÞ­„å¬/H‹Ä(¸6P »Å¤Î©óG’L¬ˆä©¦ÐXÆujÙK¶°# ó|«)Ï¿2t©­¨Ž·$„ÖGNµP]H&;À7Ûµ¨¨¨žª•Wc [¨ nE¶k~‡V®%‘4åìažW’Q”»gÎÕTy®YâʧðÆ]Q—d¬è´µ´T±K2 ÔÌ5­˜°ÇËbÖÂ/ø2j8i3ÜÞªªž:Ø%‘‘óˆ¤UDo:€A$ÛrFú®qzȼ$Ã%Íç“ÄùÜt³­$ôKUCXò3¨ÚhØ‚=6ùÇ`þ0Ôu‘É,äR„Ìm`B¦æÛï°Ûlv2ë–±ÇvjË«†ž¢ùmŸ'Oà?æ°œØåž/ªÕZ:øà5Y|,– çÔ±òØ^Ö°½°Ç&†–‹ÄTfõkðrJc©§¬…‹T¢¨6FFü­ÔùÏa½øÅ½ü{—çtVþ.æZÕÔ¸J92$•³“¡‘̺’ÌAvàpx–§Ây§ŠrDÉè¼7â9b“ábŽŠ¢jfI ¨C $œ›éÕØÝmŽ¢Éq§Ã5Eï´»~Eáø‰Gü1üCK˜EE,‹E˜%<‘¨u´IÔã•Ã{a¿ãBÒUøÅ)åñ/„複,Ž3I›T”{³=ÝQ€F:O:¯· ð‡Ãu¾ üH–SAñJžâ­ËC¥®C‚¦úHö¶ç|MøŠhs_ÄlÒ‚Ž‚£6ͨb§—á"¦z…D(î… `çbnoéŽdmk[¿DdQqÌÛýðKãf9§á‡r<åSÍOQ ÈjôÓR@¥o®ú” loŠmGáwâ9}Dõ¹5 ÖRÒ¬Âe–Fu C~–Ž¥µ0]dü»vÇKüJðýyàì%žYb¦JˆÈdŽ“J¤,.÷K ߀»p1^ÈüoàÿÂÜêoæTuæi¢Ž¦6„uÖ(U™‚÷ Ú×ì1_ƒJ~[õø˜Øè.=YMÊ2œî«4‡àFc“××t•z£F\±:ÔF¶]ü—-¾âÀcyò¼Ò«Å£ Ϩëslâ:¨é©b«®2[YÁB„ÝlCw°¹6uoæ^ñ—cÎr߈¯—$…æŠišGHšrB…/b§Hk¥¼¤ó` ³ø·Ã³ø˜PÏC[G—f4hêZ2ƒbVI‹î õ Åßó pÕ •6ƒ¾´“>Érjj¼«=¬Ëijóº'§sdó6ÜÜ1Øúà¯ÓœÛÁYµ:ÅÓ5†5pl]F¥½·ù€ïr/ýA‡ãIAñ±Ë ’ZmÑÑË!ò€ ØØ °ã/Œ§ŠDWFo”îNÇúã£4£©§éþç9e—œãû÷9ßü8Ï¢“= HR5V! Is,v-¿Èñ~pçÇÖ'âG‚ô]©ä£Ìã›Ï`˜vîn§÷Å#ð·5È2ŸÇŒÇÂô2ÓeÃáæ¢‚‚í®I"`Ň"ÅW>¸»þ)«Eâ/Õ šjtÄ‘1™´—SÈ4êmý1£Ä`å 5ê¿Á£$I~ýƶ_GœeÕy6b²5aLô³ˆä1¶–6a¸8V²æcÅÑÒÐ×¹>G@ÇG$}Iæ™ÉH˜¹Ü-“É6Å‚aÒ‰& Zdc¡ù›¿np¢£!̦ðáÊ"Ïh"žW‘ážJkF˜ `IÒXÕ3ö8óÞ“,gåEðÿS&?³÷•Úª<Æ,Ö|ªxjò–¼µÎZm)d£ù<á¤:ŽíüÛÛYáø“Âmálç+É¢¨Í#j¼àÄâ8VÔ‘U @Ò£VÜmnÖÿx_2¢Ìa¨Ì|J•”±!£¤¥øhQl0;l¢ÿ·¦‹;Í^Yê¥h>%̺²í¨ÜÜ]Fæ÷¸¶ÛzˆT¥Eð»:Øš‚KØâÓ~ø#0­|Â:¯R©n¢ Ì”}ºE—Xò“»瓎£øw”Å•å³Áaœf/$ã[fu]y†•¸»Pyôôúâ|ûÃÑSAP™=IÎkhç^\±˜!7¹“@òÚÇsk÷87ÀQ²dš:p¡šVe1T4Éè|ÍënWÿ‹zgí¢­vÙãTE4ŸÄäck'—þû P¼uàŒˆøÞ¯Ä¯“QÖVVtæ`Ä#é±Ò ‰AÜq~øéRQå´."‚ªS-IòFæà6Ûo_LŸÓTÕÍIOK³Èñ¹*–R¡Jݵ»kÜörü;ÌÑäk»öäçé7`>Aü e™E- Kjy°INŠ ••-º±V*lMÆüP?á±+S±?2,º@ç–µ¬æÝ±d†ž¯£^0³, H·o…+¦ª—ÃsA$• ©^`ŒªV5¹g»r¶¸Í»_¯6mJ„•FÙ|%)eŠ}XN_ÅÔÒçNÇ®ÙjÆêÀê*÷ßqb·¾R4R»•b•·~׬‚º¦¿Ã”™M ËÞh.iõêû‹¾6¡•Ö®U6±õÇ7U?#6É.YšY,‰P>O_4¹«ÐTSIDr¼½MI)¸îî®4ÏŒùkUfµ ×¥2D HÔÝO¶Àïêp}O6l¥ÀŽ’`Hå˜úþߦ&Ÿ.̨¦øb’jôÛUÃ&å‡c«Wí‹qi¡,?Í}Ý}Rà\pYVßíýŠÌÍmèò j¹äVi+ªÚrdÓi{*­‡.ö@±ìë/£ÍÞœfU¹}2I81RÂYw"ýF-f‘Fäk‚ùÀYT0³Ã›$¶dÈ”«#›MbBŸrïõÅÆi Ã"¨óqßðÜñÍ¢©6ízûû°dÝŽšUI $ŽRB-½Y‚ë‚ès TY©P·ÄF©#ƒ¥õ³ZÇäm¸Úö¸¸µQCR‘$×*qìAR?|BYšB·ò¤cHõ,Ð~ç:™é²]z4¾ó>ý²n=çÙðË¥¤¤×?¯$µR’#€!P¥»0_¾ÑÒ´0K&dci\üúî·¯¦äb§âú:…’³4ðîcOˆ" ZEø¿44ÈÌβ±óÐI +°½ðKgíMAü5m,ÈìÒM1,ÿ3wg îMÏ|uåž1m›ø©–y¸á[Ÿ!‘6šøB…GòmÀµ¿¦,IN¥XbYùœ ¹Åj#y¢%Îpúš=Q’·-½±ÌðL¹d—7ïúé¦ÜåDGóº"´ÒkrìÖäý¶%ë£JñFàº8ÊH¸¡ïâE¡¡55V†(c2ÊÄü¶?¥±]ðFqMœœÒ®–ŠzF’¬<‹4æF$ƶ6áv`N:Ù²äÅ‚*|?Åû›±Í­©öÏ|\ e-E€ïÀ0力~ç 鄹®GKWOu–Z)‹rd¬/ÇÎñ,©K˜åñJB¼²9U7%Ž¥ØîÿvÄhrƒÈÅâ[…Ó¶<Ô%³[¹ð•wòHãdÝçܺÿbÓ—Ÿ‚Éé(ƒ‰LÇb9* _ö¾*é_H’6f ÊjçÌ¥™F’B6¸Ã`Ò¶CTúÛ¨b”‚„^öa·¾ØSø] ¤ð¬3I•jc(ÔLJ¢íno©˜œudÿ”e'J¸_3l·fQôõ'”ƒ]Óeb%^-K~›~¸u—˜Ä)Ú6IF†Gÿò_k[Ó}ðPLª Ê–‚7–š œNáVà~ƒ s䞳°WÁG5EU7Nª!„d¸$°ÔE‚ÆÝíoLdÑcž“>îßE8ñ¸»õeÔ–GIDj^ SÆ"ê8³2¯Û½¬>Ø/†)2œã&¤­A™¥L“º;\+3k…˜s …ÞÍß ŒgàQªf‡®#Pån|Ã÷=ñ´ŸÂòô|ÌSF+36†›Ë`ó0¸E¹ôÒøêé±)ê& ûFœpjÑ¥ H'N˜Óh¤†:Oö8Š¢¤¬2ÔHþf)?SaýpêŽ05<#n;a}vXóR˜ãxÁ¬›žÁÃ[öÁŽ,¸ñU{ÿð\Úil[XŸ<é>SP“̰ÆÑ¶¹ì‚×-öÆxR–h ¦ŠTh ,5(÷bnEù7Ä~$Žœe²Á[2ÃO:ôå'’¤ù€ØÜ‘q|%šæÒVf^u5Tñ±–9i©,„’ oµ¶Ç"Œ£%9ST讌²|O¡ÖmN¿µ(xˆ4U%¶ž9ãät­,´rÔ¹IQ,ÀqÈ‘ýöÆù­Q¦dÈ‘¨vÔì8MÀ÷ÛÖ6gÿ¦je:Ö¼.È y®G—ïÆØ».M™ˆŠæí¯™w¦å_º²ÓÑfG*¨ªÊþ.%ŸâVn³Fi¶bÊ—K5ï¶ÃÛøxÔf(¯«Ž*˜r˜`Šƒ,YâhÌ…Yši¬Ö'Si»é¾-y –SEU*"ÂA"ÎÖ·úíí…µÓÔ=8“¯4ÓN~žH¡‘¤o#àçÙN:ØñµRæOðJx×±.]˜Câ<Á«¨ú “=-U rJó°íÎ:šmÄä¾Òtÿ#~,UwöŠÞ_šÓÖ¢TT‹UÖ¤qDðôå‰ÔëÂÿÊV׸Þ÷Á™Ð’ æ8$ cS,dn­rG¨¤øz|Úz/ KŸŠdª¯ª¬««@¡UGNFBý—@½íúŒ\i詨²ú» G ;¼†Ì]´ }ïÆ×ß),–9÷|?™Cãj~¿îWsãX¾&Èê&Ì)é2šH2ÈG^iHŽ4=»‹{âxÊM0NPHT›ÿ21Sûƒ‰–Z_SdùŽYÅ©òÙfMÔØXÿ+-øô*yÑ5,TP-=8c:Ó°f%îNøàøšžG4»NŽvxü¾SÿúYúñ?å”1HS̾Àýö#_Äjéòºœ¦z? IŸf5}ZZ8~2 u2X>’Ò›î·PM•½F,™L•ÄED#ƒ0íÿÕ°Nt´4K±êxÈd³”`Ö¶ Ë¸ ^ß쎴rãœ<Ì®•°íœ7>¾eS9̳<—ÔyÆkMK=m!ë" ÔкØjXï¹XØ›€ml"ñCC—gU S;A–#©’ÃY…M4á'Ž6•HQü ’7Úä.x¾+„^GLÏ7*6Ìrÿô3Îê`ËÐ!S0Ò²ONþƒx&§/ªË)'§ª†ŠjéÚ‰ ¼–µžãm$Gµ°Lù§ˆ¼I™äu¹n]ZcŽˆª_ˆ†$ÿò‚Q‡kî#kááøŸà(*¢¦¹æiª…\ñ¬oRK$šËe]J»¤¾:Ù¤²èT2§ýËñ%,I?r½Ÿø'& Í³˜ëæ4T¹œŸL0³TG¨ÚxÕ­¤ͨà·x.–šŠ(h2É¡¥Ìݺ³NLQ1–fï!Ô/¾ÀXqއâùg‹/3QEHÕWj•ò4e‡P‰à_ê)¾øÊ™ÎcVúÍdáâ{yž ˆ‘³ *u‘÷·Í‡ñ*þË‹½­#gˆ4ðÒô¢UÏ6G[•ÊNU™ÍAw,Y#}ö³ØznØQ‘ÊÙgŒóÜŽ²zq5eGñ Xó´LºNÝìÑßn5 á÷⪋)•*©+M™Ô?6Û|¤thä3°Bÿš¶-î=~›c™æÙ½?âæe ôy×ðz© ¦”KA/ÂÔƒFút™®×RIÜvÇVø.ŒÐÈÑ©”#F¯ªæÄ‚GÒà S›UX’9˜FN¥hÛvÜoék}±V-N-2”³'ʯ¼Ì« þe‘¬pÇÖf2±f,FÄ‘Øûb r©U kùózà×I*™Ž¢€oÚÛ⨔©ˆ]P±a¾Ç·íŒ3Mj}zœSwèCŽWÇϽ°»ÆYFeŸøÄ9>T!9†a–ÔSSõŸB $B€“cë†fF“Z®ÚÂÖÚØ‹7Š€ärRgTóMEV¢)R;‚ÈnNà†[˾øëé7'虫Š’^ˆ¦~xGÄ^§«_gÙ5Lrª(Žš-1Ó²ÏeÝÅñgÉtÒ…‚£/ˆA)˜‚a[eï±î}EñVðîG‘ £ÄTtY= 6Y5qV–~¢Mdž,×:®^ýîVå¹t &sŸg4ù|å²Ò±ÝdŽ77•îÇIQ¹M¶Åøç,ÚüR·øQfl«&ßÐ}LŒÑ΀²†V®-„sÕSÁ‘š8LírG2kÓh‰é»ïÍÕnvÃè*â›óiåE(©¸e;ƒ¦Öj„D5V*–îOÿ'õÇ2Y^Ñqå¦ÿ å¶ GŸAžouFU˜Ñ嵿WQM$pÔh ÓvR±ƒÎ9~kàüÅ?©ëÖ¢Žšº‘OEVQ²êT É©QÀµikŸñm¾øêô¡ ¦"’"€Ä‘fù…¾‡¿Äys§¦Šƒ8¥ËQZ™$’Ìà `¦ûn|Ö6?AA¥Ë›ãsV ³„”—ÀÒæÔ0Sd5çõ±ÍNÒütuâZ¢t\„ˆ"…B˰6õç‡^”U×Áiâ¨/NOñš1¨‹ßÊ»«o{ðC’1˜Çÿe”5[W²+ñDüåô+¿„qWÃâÈ3$ðõT9Ek˜^¦³-–)†¦Ö‡Hw@,Nೇ~¶Bù”››arJÜÎ ¶„fÓG5PŒ ƒYXÛ°Ôloîp4’2 ª„aº`±¹{›ñ‰®×ÃR ¡Ú|-fmõ!2e£ñ=SÉ[#.g#åÒ*ÄŽ–™Ê…$^U'¿Þá—ÊæUâ‘¡G"J@ó¨ë¶xïÿ妤øˆ• Õ,r BüâÃI÷Ûúâ ºuªš¦XŒþRT5¿Fï…ÕgXµKbå%ߣèµF¤¿¨ÄTt5ÙÆTSE Ç™µtëè:Â襭ɻ)ßÓf‰fº %AË \–ãõê\êêÖ®ZEÝ~b×$ý/÷š©)©3ZÈs$«¢vD‘æìxãû›a5^d3ji&ø3KÌÝMzðTò?Âl®•dÌéòZ “Q±5HiX†'ˆҢÍ{ÛÌ—%¥Èª!¯Îi²ê"gJz xbAs{@¹oÿ·Íñuy–_SKM–™uD)ÖÉ  ¡ÖâÄÙ…øØqp0ë?ðSÕˆ¡¢‘t´êeÇ£{®=^}LeŠN/”Ž´õ ]•¥š¦OÄYcž61´N»Æ($+rG¯Û¯STÒx‚£2ZZ¼¶¢yÌ+SòÃ×@]Em«·7µ±Ð¢¤¨‹:­Í*þá¤t*ªu©#ó‰ÚæÊ»/¾ ¥Ì$‘Èq·éŒPÏ‹E)¿‰ÅË,a:}µESÄô´õrSÃ;Hå\~^ª1[Zç_oP;\á ÿ†~ÎrÙó ÿ©ë3™t2¨¹.#&ÄbæÜ¾-(Ìh©³ì¶ìÁ²Õ¨IÚ9V3¥yYØÙ‰½¬7ÀòWÓÉ]–åyò-\“|LÆXLS4dì[qp-Á¸ß¾,ÐäZ}5üØ0ÏÊ…|Ù§|á_e•xW*9]>a8©’rÚ UPæÀÅûàïÍ]No_Ló7Z°nì ùcU@˸$ïsßç“J)ª©‘Ò2OB=n½®sÉ·¶"ðˆ2¯å36MC_MGK1€ÉYOÐw•~kÆÖpx7 ^øäè°½N\š‡ïÁ^ÝÎý€ér¡-gˆ²Ó=HJÉ •<ˆ”6±'ß×|[åX`B¢Ü ý°$5QTWÕDZjVX‹ T>×çf·· ãÊö}iä(žç™–%&ÒoŽEœcçŸxƒÂ°/â®SâE¬HtL8E!˜´ŒrIé‚ \Ü ï|^¼I–SfSeÒTÀÓ%4æA` S¤ÛñŶß|W–%Ml™ÍÓ¢šN»u5Û¿­ù`ú dâ’Iú²ÒÆ´òIþ7 .|çË15Ù&Y&aD‘Ë>[¥ B<•#PÓæÙ®XòJžÆÎéH„º,fR0€ßNÖ·¾Øhôo>w[JV$E-?; v¿°ÔoLQMOw©,Çùˆ¾Û .·MlÔ©G÷eY å_"¿œæ”93ÁSšKO-Dß ’̱é˜(ˆ®¿|4´”µùTÕ-+Õ–•"% ¶"ï#F  {ò,8ÁpKô͉I¹‚O¶àí„ÕUÔÐçHÕóIÔT$TQ$=BU#yO „Õ¥îÞ_•w½±4ùqáÙ(»bÃjiû‡f• ñ $rW«)¸ ŽÞ؆ŠW¢J¥µt[èlFÇלev‰%- ºVv°µ¶Á4‘ı™õ` … í|qpäž]dúßâejRÉÇVY™Ašey˜Ž)’JPôõ௜ƮB–µÅlFÞ˜ŽBÕoþ$Ò~·PpÆHéÛà ”ÔÓQÂÔÅ)T‡PHÕ}ï`¼ï…Ôh©WRå;ÚçÓIn1W‰nÉ™ÎOØ£Uæ@yEG±¢üÛ³z›ã̶ŠhóªúƒaO40¢­­çS&£÷ ƒí‰ü?NÏH]¯¤ÈÅI;‘ÿÝñVɳ ·ãVyEKâLÚ§;l²1&Y oƒ§Š&´~[k-&û“¹íŽî-òáŽYªHߦƪ2=¡Ÿã<7P”ådà•cw:9ý<È>˜¶eU"«-§¨Y ~´ v…àkob9¾ø«ÏЦ©«ÒS©*OÄ*I¼fBX‡^×רzß*9£x`TU…ºd"i nÖûã?ƒæxá,3UT×ÐÍŽnq~€“¡.§æ ~ÇËo뤨‚ő勇ÒçÓI-#Õ×¢ê.•L\›HÓk»ßüÕõ:põ,š ê±ßÓ¶Üã—U Ñ?æ¢îmï‹="$qj"Æ÷ÅfG1ͪ?™ â×ÈòÓ+ÎÖÛQ8ÍàŒrJ)søi)I ?UÇü:\µf§•°È±E5ô²ÛÍAm®v¹­þCSKáŠQ_C s3=TQ±`¯v,~kQqpm±"Çg¹ ùŸˆéê«f)F TòfU`V2{‚t±ÿ´ŒI"ÆXWå꾊 ‡÷ÆïÎäâ¥ÝÑdåYf)¹õ%TšorÈ€ï¹ û\þ¸Mâ:È|?áêÜÍÖá$ò‹ìÅœêØ›SÑÂZD-$ñ†“ò«6¢>ä²á>]‹ü9šåuȓԙ©Ä¬ÑÕÈWQè >˜áj0ïÔ(>ßû3$ã»7–ûì'ÀsË7€rj™™z•‰1'k—:‡?÷ažS9H Ëá#E$+>Ö?{ˆ²š2¬«/ÉÔjŠ‚š(T7ÿëPý†øƒ04–h/ÂPÏPoÛJí¸²ìËÇѯÀ9¦à–ß’x鞟Ã…d“ÂPUÈd&Á‚ÀžÛ I˜ÏI𤗧«£‘“afÄ0ö'õĉJdü?Ì¡ëi©š%opöF¸ô³,ª‚X²\š$muPÓ@†Ë+ˆÒßåÛQïåßâpŽ,ŽIòéšfÚüe‚÷o®¤ÄeAæxµH¡ÀØ¡$~÷·Òødò­€Üííƒjhä¨Éê(d˜A<ôÒD$˜ÙÖ×þÿaŽg…)FS’¾xþåXÔ¼×^ÀË_Y¬èé—J<‘;^Ûù…ø½‰öÃvc ½†ûÛ ª ÙME4’$PèêI»µ—’{“ƒiËje ÞÆãí‹!’jJ2•Õþ¥rRÚÿ}”ïÔ$™…^çTeKÈ  › ûZí‹…)écÊR¾H›âëÕeõXÜ‘Ïa¨â©›ÓÇQãd1„"¨ŽöÖ¶c¹çL^z+ÑŠ*T"4@¨£°Ãûc›¤É/6sŠç…Lͤ‹óg9}(‚²¦‚|ú‡.F&xÓâYXˆ÷‡¯›lo–etÙloCGñ©Q,ÒKQ!‘‹¨›Ûpì±íNIEünƒÄCZÖCA%¶ÚãvŽKpcÛÓSzá†V‹_ôÂ\êï}ïnØõ°Ó¥7¾­ÓÙé¹l÷ÿà“ÅÓ˜( VêÇ%0k•}1Ôm`6#M÷\V]fc ŽzÇk0&•V-ö`MùëĹ´|NäÁgUÌçËû/ï€ihêž )Ôjdc¾ëæíÀ7Ç™ñLù笔qÉíêr5¹eæì‹ë§‚©z¾!­Í¥‰Äp¢Ã8ù˱_k¿¾øŠM˜`¨IÁ‰% Yp#‚©’8 “À¯0:žY•>Ü㳬Œ4Þ±'Ù¾XüŒ;S*ÙUZ·Šªr÷–‚ðeú’0¡ªS&£¨|«ºùM‰ ZÇÿÉ”Px©+rŸ øeóVªãj(ZyĬRF¢Ì.Úb¹Ø\‹ã f2Ôxªº#O i9šDu‚Ï ò…gc½´¨z*d4ß‹â£,ƒ4Ìê¨:RV%=b!¥…¢S¤ÈKFÄ–$5‰$¨O Ã,rŽ,}mWïß¡V›œÔaÕ~èºøv‹Ä•ßQœf•4U•-€Ë†D[°%%Rû‹mï~m‹¢h¯£›,Íåx™*!F%^6ºß}ìG鸾ØQSIM+Óæfª\ºiM[Æî"ÉR:’«rÃIÕbEï…y>c˜ËŸÖ½Nq•VVšt‰Ýu™YJŸò›cµ¤þ\g>íÿ.;™´ËçZ9%¬£’‡.§0«$Å¿/ù®x€/¿ ¼C›ærxª::FËゞš¢ªY¤b "§‘Ç Z÷'Øp7ÃJúª<»ÄC“¨9Žu´’0Õ FƒKH ‡E¼Ä’/|•TŖ屸Ц²¡je£š¥ø›Îí#S#¤I ô&øÇ-&+Ûu\’Xñ¼Mß?šÏxfާ3¦ŠÆ/ùm}#sî.¥ã(J‘q¨ŽØ 1I¢O1EÕ©‡ø…ˆ°ÿ}±7€|gá¼Ö´äÙfd²Î°õXI¤³¶Åä7Þãkßì0ŸÅçù‰úù= Õ´ÎJ¥ZE±õ6ÞƒÏÒ,˜¡(;çš9š¨Fxã(rXrzZÇYs ä:ƽ;]y¿ïo¶Í樧§ªª‚ŠjÙ!¤Zh­®[J­Í®ml–f’E’ÐE6Y,m;˜ÊS¥Ö+“f ØÇm¯ƒÅO"T•$©±ÓßmïŒú9COŽ/õ-Œ!µ$þ¢Ì(Фô¼’Ï©¢""AžCcmÎæÆÞöà ·=¬ªÊ¨â«Eޝ«•¥Œ¨–3ÌP>RHàñ¿k éKŠá€,TÀ°ÝE¸Qņ£sL³?y¥¯ŠNšR8žÀ1MË-¯¶ÞQÛ¾&›Q<d1}”ÚäXNQMcêÝ ÌΞ*œÌÅwª †Þ]ÔÙG¸ÿLG”æ âß)¦ª®¨˜Fµ%¤ƒL*¥ŠGÒ5n¾§Q,²æìa 5€Û+X’OÜŒ[)¨é×-Šâ"Dl7q‹¼/ñO3ˆÚe“wbqþŽF÷°ß4˜£›2Å7Izˆã¹Ç‘'€2¼Û 9a–­==EÑÑH¯¢«å)ëƒüNùFiIáèh^D§¤kÔX$k¥”(Ò6¹»€Ü †-ÕRfñ½ZE!Š Ùi¥/åè˜Ö%—p7Rx àšqCF%hÚòLLŒ ¹; ½»c¯/ Ç;—™QìÐð(Ímt—'µ” WA9F ¨5×Ë¥®-ï¶A“Ë—ÓQGY]\ѱE0ÓT‹íeØÞøW[ŸË[â˜(fšHòèæÉ_#J~@ÏÍÅÔûlyÅÊ(RH0»FÖQo”ãN_#Q, ý~ôZœu Åz”Ÿe¹}8¡«¯øùÍm]I›ÏòI;º¯›*•_¶Ûa¦_áÉòÚ<Ýà¥J¹ëëª+)\c!°M!~÷Á>âÎëaœ–”6÷ù™ô±ûáìë^[,R!1¼eC$¸¸Ü`htpË,œ6Û¯ ˜1'çÛU9›Sº¸‰VÀñå#oN1TÊü2|)•R䋙͘SR‚”ÒOn¢D’6?ͤYAôy“AU—äÐQÇ$3TBÌ‹#"¹Ð¬NþUÚýíïjŒÏP±Õt–e°~™Ù›¹^qÊñHÂ8¤”{’¯ðfÔ¸äpÊÖ _N’>ÅN<­s3V$I,±ÂÁDŒUEí¹öÏ–0Éå_¢3ä©ãŠ~ƒŒ¡©Ý3ºjR{{a'äY2™Ú®º:Zuu ,— —`­¸ÞØŠ÷' u©‘Ä13³ôÈPªT¾çæ® ÎbŠ»-žœ7äÕEmz°"÷í¸³Fzm*^ÃK"Ú¢úù rܲ›&ÈirêEÓbRÖßS3ßÞäþøM™øw$˼O&e[OO4ù¬PÓÕüLß”ñ™4ôîokÞÖï°²WUÃ6uMÉô‚¬Án{ z÷ÛÓ ³ ™ÌsÕÕÕS¥=\kÀ¢çÌ[IÕu±Õn8ã{c‡¨yÏ#¾X¸¼¹j*¸ô,RQRå•£/¥ˆCKOG \Ø Pón0³1G†u‘f1X3à882j™k4ST<ÓÃ9Œ³Æ#m'u½¶ ¯a{_gó¼rÇ.•ºj(I·òý…íƒ«Åø©F|+ãè&xÅÍÅð·d•ó&§GS ž"Yoå}gpl-§o\4Ìé–§)–ʨ³Vˆ‡JjÙtÂöØ–¸+°$îGIP’g“VH)éèT&»8X€nàžûs‹ ÏIWN&†JzÚ*„(ÅçŒÇ Ãî mÁÎXŒ³z{°Ç´Š `X|ç¶3Žûç_•?uùeÚ%‡j™ÀØjÐcŸ~+TÏC—UÕRHbš:j‰QÇ!Ò7*~ÄöÆc1ÖÕ$ÒÿÛõ0æê?R½ÿ "μEøAšçY„••“ÔH$•€¿1Æà8QŽ‡á ¦—*ž9eyÚˆcÖu‹#.w6c1˜Åü鯜‰oÞÆ5îÁa[ílAM±6õÆc1‘;|þø'õÏNQ–f쯙ÐÁVÔìL-"Ü¡Ûqé…^aUšæ²TE ’Ñ:ÃO+D½HÑ£GemV,ÄØœf3›ÂGé/Ì׋¤kã,³(ð/‰óŒºn…u%ÒA.ÚPlAQ†ž†6ðÅc.ªŠºh¦žBnd¨»sëŒÆcg‚$ô*þ©lò¾ñÃ&P±µd&×öÆc1®Bm{¢‰º‹£!ÿ­õ8IT‚ibŽáZWfÞ÷'¹?sŒÆcâ®´òûÿ4QŸì/ߪ=„ ÏùpÛ/U¡ ƒ{q˜Ìr¼ 5~ýQ~0™•YH`Àµ ª«¤±Æc1èuðÉ×5ú–¿²'[·ˆ* &éK]øšø2¡˜Ò¾çƒŒÆcÎaoÊŸÞe›vþñm  ¹Ý­ö¶&Ψéžlªv…L±HìÜ ¯ô$c1˜£EÎß±^›œlŽ`µ¶°Ã¾”ÃŒšZÆH6ãlf3üygký?©fÌ€k)¡Š9¡D²1f ’nXê'rp¹ãA]VÁ@=8«ã1˜«W¾¿r¬énþÿ©g¢i"4ŒP| åt)«Ìé)Ý*«+sG¨s;°sñ@|¤Ã`Æc1ëÒÿ§‚ù#tz-Ù¾_IPÉ,±@ª.Ê3X†€Ãë{vÆðe´u9†‚ŽhË+$ú“ëŒÆcáÓuÍ"N+º+{æõ$ò'$}zC r`57°Æc1âp6µËÿfq´¯ùïïæ_þô£ÿþRÿú˜ƒ3v†‚c鱯c1è|Yµ—'Ö?‘ÖÉö×ü ë6IæØw–K!Ño.Ž-ŒÆcá²qÌé˜tî³?¸¯øƒ,+»5S1Ôå·Ò=N!ð̲Kâ,Õdb©ÄwþPCûã1˜Ñªþ¤>¬wýXýÿC%kwb—?øœIà×hëe¦Kº+&›˜»Üã1˜Ëƒþ÷ßù™0¿ú˜ý?PœÓËW-¶Øàj Jjêÿ…«…&Ñu£ †±&ÇÔl6ãŒÅºdž¾)û‡*¼é?pÿ36OP„ùX”#ü¥.F–1Qx|ÆlED ~vé°þ˜Ìf:ž+ÿs#TÿªÆr‹•¿­±*ÿûË6• ·ä&3Žf‘ÿÓÏÿeù1¢¾'÷~£jUWG,!…®?Ê0¶OÿjmûߌÇKU°Aü‹sÿ§ê&§‚¼1g,jõ…`S1ù¬Öý¿\ZèAÈ1˜ÌSáQ^n'^‹õtþKõ$«ÞhT€A'cœ— í°÷Æc1èòÿý_ï¤_´s|ÖÏŠ(œ‚Z¢¦g”–'S#*§èÃú%V­2vÔÆÿsŒÆcůêKêŽ%-ëêkã™*,©cm!ꔵ»•‡è@8Æ’É%Dѵ¤C©M¯b3¾1ý&¿õüZž¤¾Ÿ‘Gü7&ÎX#:cžä”½NxÃ/¢ogþ24ÑŒÿÃTO”×(Ó$¥ÖÛiYÕ¡Ã-÷¶3ŽÖŸ\+ÿUVE_øŒ29ž¶Ÿ §­ÓUvDeªYÔH&biïª÷½úqÆÿLY–Ð'ŒòzØé"Ž¡`D é²×"ÿíÌf,ÓÿÚ¿ß©n•|R_!Ô”´Ë+Öˆ#ø†êÄdÓ¾’¬Ä~¢ÿ¯©Ç-¨¤ƒ0ñ†O–U¡jFŠedV(YZW¸%H$l6'¶3†È•/ß±VOè 2¬â¿#ÿˆ|¯ÁY;ÃAáýGOO lY‚êc¿$œtßÄfh²™*âwIà™Ll¬E®TñÁàsŒÆc6·Œ Œyat<ȉh£v7/N¬ÞäØßT¨ÖÛkc1˜£:þF?«þ’É+‰ª%Õç Eý‹[úbÅ4):Öªž»RôË$i °±Û¹íŒÆcŸá½dûÿ1|9ý¡6C=\…–äJqq”鉭µ†3Ž¿€$´²h»ÃÕce$%š¼±'þnN~§TM"çYE( ÁS3$ÈTà! ûŒÆcÎxõ¾ÿÔ˧ûýú‡øb†–ƒÂttô‘tâ:‹1õ8ÆòŠÆ2 *}9Æc1ÝñERÓô6æí~ýÎ|[Q[â¿áUf)¨î* 4Ks!ÔKµÎàr{bùãjªšZœŒÓÏ$]Jäôµƒ)µÁÌfgN¡Vf„FŠ zh˜ØRIûã1˜§Âÿ¡36ŸìHÀša£\h‚TVÜ+†>aèq˜Ìf+‹à–ÿÙbobcat-3.19.01/documentation/man/hash.yo0000644000175000017500000000647412222576536017050 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Hash)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Key hashing containers) manpagename(FBB::Hash)(Various mapping template classes using hashing) manpagesynopsis() bf(#include )nl() manpagedescription() The bf(FBB:Hash) group of template classes offer hashing-based mapping. Various variants are availabe, all based on the facilities offered by the bf(unordered_map). The hash-map offered in the bf(unordered_map) container has a fairly complex construction interface, and tt(Hash) is an attempt to simplify this part of its interface. In practice, hashing uses a textual key, which may be bf(std::string) or tt(char *) based, and the keys may be used either case sensitively or case insensitively. tt(Hash) merely requires its users to specify the map's value type, while the key may be a tt(char const *) or tt(std::string), used case sensitively or case insensitively. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::unordered_map), using various instantiations. manpagesection(TYPE) All variants define tt(value_type) as the corresponding tt(unordered_map value_type). In practice a tt(value_type) defines a tt(std::pair), where tt(Key) represents the hash's key-type and tt(Value) represents the hash's value type. manpagesection(CONSTRUCTORS) Variants of the tt(FBB::Hash) container are available for tt(char const *) or tt(std::string) keys, used case sensitively or case insensitively. All variants support default, copy, and move construction, support construction from initializer lists and support construction from iterators defining a half-open range of tt(value_type) values. The following variants are available (showing their default constructors). tt(Value) refers to the value type stored in the hash table. itemization( itb(HashCharPtr()) this hash table uses em(case sensitive) bf(char const *) keys; itb(HashCharCasePtr()) this hash table uses em(case insensitive) bf(char const *) keys; itb(HashString()) this hash table uses em(case sensitive) bf(std::string) keys; itb(HashStringCase()) this hash table uses em(case insensitive) bf(std::string) keys; ) manpagesection(OVERLOADED OPERATOR) In addition to the index operator inherited from tt(unordered_map) the overloaded copy and move assignment operators are available for all tt(Hash) containers. manpagesection(MEMBER FUNCTIONS) All members of the tt(unordered_map) container are available, as tt(Hash) inherits from this template class. manpagesection(EXAMPLE) verb( #include #include using namespace std; using namespace FBB; pair ap[] = { pair("one", 1), pair("two", 2), }; int main() { HashCharPtr hcp; HashCharPtr hcp2(ap, ap + 2); HashCharPtr hcp3(hcp2); hcp = hcp2; cout << hcp2["one"] << endl; } ) manpagefiles() em(bobcat/hash) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/ranger.yo0000644000175000017500000001052712222576536017375 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Ranger)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Error handler) manpagename(FBB::Ranger)(generalizes ranges for range-based for-loops) manpagesynopsis() bf(#include )nl() manpagedescription() The tt(Ranger) class template defines ranges that can be used with range-based for-loops. The standard range-based for-loop requires for its range-specificiation an array or an iterator range as offered by, e.g., containers (through their tt(begin) and tt(end) members. Ranges defined by a pair of pointers or by a subrange defined by iterator expressions cannot currently be used in combination with range-based for-loops. tt(Ranger) extends the applicability of range-based for-loops by turning pairs of pointers, an initial pointer and a pointer count, or a pair of iterators into a range that can be used by range-based for-loops. tt(Ranger) is a class template requiring one template type parameter: tt(Iterator), an iterator or pointer type reaching the data when dereferenced. tt(Ranger)'s users don't have to specify tt(Ranger)'s template type. The function template tt(ranger) returns the appropriate tt(Ranger) object. includefile(include/namespace) manpagesection(FREE FUNCTION) When using the following free functions, any (subrange) of iterators or pointers can be used. With iterators subranges of em(reverse iterators) can also be specified. The bf(EXAMPLE) section below illustrates the use of the tt(ranger) function templates. itemization( itb(Ranger ranger(Iterator &&begin, Iterator &&end)) this function template returns a tt(Ranger) object for the (sub)range defined by two (reverse) iterators; itb(Ranger ranger(Iterator &&begin, size_t count)) this function template returns a tt(Ranger) object for the (sub)range defined by the (reverse) iterator range tt(begin) and tt(begin + count); itb(Ranger ranger(Data *begin, Data *end)) this function template returns a tt(Ranger) object for the (sub)range defined by the two pointers tt(begin) and tt(end); itb(Ranger ranger(Data *begin, size_t count)) this function template returns a tt(Ranger) object for the (sub)range defined by the two pointers tt(begin) and tt(begin + count). ) manpagesection(CONSTRUCTORS) Below, tt(Iterator) refers to the tt(Ranger) class template's type parameter. Although named 'Iterator' it can also be a pointer to some data type (e.g., tt(std::string *)). itemization( itb(Ranger(Iterator const &begin, Iterator const &end)) A tt(Ranger) object can be passed as range-specifier in a range-based for-loop. All elements defined by the range will subsequently be visited by the range-based for-loop. ) The copy and move constructors are available. manpagesection(OVERLOADED OPERATORS) The copy and move assignment operators are available. manpagesection(MEMBER FUNCTIONS) itemization( itb(Iterator const &begin() const) returns (a copy of) the tt(begin) iterator passed to the tt(Ranger)'s constructor. Note that if tt(Iterator) was a pointer type (like tt(int *)) the data to which the iterator returned by tt(begin()) can actually be modified, as the member's return type (using tt(int *) for tt(Iterator)) becomes tt(int * const &), so a reference to a constant pointer to an tt(int). This is perfectly OK: if the data themselves should be immutable, then the data type must be defined as tt(int const), which is automatically the case when passing tt(int const *) data. See the bf(EXAMPLE) section for an illustration. itb(Iterator const &end() const) returns (a copy of) the tt(end) iterator passed to the tt(Ranger)'s constructor. ) If reverse iterators are passed to tt(Ranger)'s constructor, then the tt(begin) and tt(end) members return em(reverse iterators). Since the intended use of tt(Ranger) objects is to define a range for range-base for-loops, members like tt(rbegin) and tt(rend) can be omitted from tt(Ranger). manpagesection(EXAMPLE) verbinclude(../../ranger/driver/driver.cc) manpagefiles() em(bobcat/ranger) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/osharedstream.yo0000644000175000017500000001430412242407226020744 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::OSharedStream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (std::ostream on shared memory) manpagename(FBB::OSharedStream)(std::ostream operations on shared memory) manpagesynopsis() bf(#include )nl() Linking option: tt(-lpthread -lbobcat) manpagedescription() This class offers the features of the bf(std::ostream) class, operating on shared memory. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::OSharedStreambuf) (private inheritance),nl() bf(std::ostream),nl() bf(FBB::SharedEnum__) (cf. bf(sharedmemory(3bobcat)) for a description of this last base class). manpagesection(CONSTRUCTORS) itemization( itb(OSharedStream()) The default constructor defines a stub a bf(OSharedStream) object that cannot immediately be used to access shared memory. To use it, its member tt(open) must first be called. itb(OSharedStream(size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::out, size_t access = 0600)) This constructor creates an tt(std::ostream) that interfaces to a shared memory segment having a capacity of at least tt(maxSize * sizeUnit) bytes. By default, the shared memory segment is opened for writing. The shared memory's access rights are defined by the tt(access) parameter, using the well-known (bf(chmod)(1)) way to define the access rights for the owner, the group and others, using octal digits. If construction succeeds the shared memory is ready for use. If construction fails, an tt(FBB::Exception) is thrown. itb(OSharedStreambuf(int id, std::ios::openmode openMode = std::ios::out | std::ios::in)) This constructor creates an tt(std::istream) that connects to a shared memory segment having ID tt(id). If construction succeeds the shared memory is ready for use. If construction fails (e.g., no shared memory segment having ID tt(id) exists), an tt(FBB::Exception) is thrown. ) Copy and move constructors are not available. manpagesection(OVERLOADED OPERATORS) The overloaded move and copy assignment operators are not available. manpagesection(MEMBER FUNCTIONS) All members of tt(std::istream) and tt(std::ostream) and the tt(enum) values tt(kB, MB), and tt(GB), defined by tt(FBB::OSharedEnum__) are available. itemization( itb(void clear()) This member clears the error states of the tt(std::istream) base class object. itb(int id() const) The ID of the shared memory segment is returned. itb(void kill()) Without locking the shared memory first, all shared memory is returned to the operating system. The bf(FBB::OSharedStream) object is unusable after returning from tt(kill). Other processes that were using the shared memory can continue to do so. itb(void remove()) The shared memory is first locked. Next, all shared memory is returned to the operating system. The bf(FBB::OSharedStream) object is unusable after returning from tt(remove). Other processes that were using the shared memory can continue to do so. itb(void memInfo(std::ostream &out, char const *end = "\n")) Information about the tt(OSharedMemory) object is inserted into the provide tt(ostream) object. The IDs of the shared segments, their sizes, the maximum number of shared memory segments, the number of bytes that can be read from the shared memory, and its actual storage capacity, etc., are displayed. Following the information about the shaed memory, tt(end) is inserted into tt(out). itb(void open(size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::out, size_t access = 0600)) This member creates a shared memory segment having a capacity of at least tt(maxSize * sizeUnit) bytes, and connects the shared memory segment to the bf(FBB::OSharedStream). A matching tt(close) member does not exist and is not required. By default, the shared memory segment is opened for reading. Different from the open modes used for file streams, creating a shared memory stream with open modes tt(ios::in) is OK. In this case the shared memory segment is created and once information has been written to the shared memory by another process it can be read. The shared memory's access rights are defined by the tt(access) parameter, using the well-known (bf(chmod)(1)) way to define the access rights for the owner, the group and others, using octal digits. If opening succeeds the shared memory is ready for use. If opening fails, an tt(FBB::Exception) is thrown. itb(void open(int id, std::ios::openmode openMode = std::ios::in | std::ios::out)) This member connects the bf(FBB::OSharedStream) object to a shared memory segment having ID tt(id). A matching tt(close) member does not exist and is not required. If opening succeeds the shared memory is ready for use. If opening fails (e.g., no shared memory segment having ID tt(id) exists), an tt(FBB::Exception) is thrown. ) manpagesection(EXAMPLE) See the bf(sharedstream)(3bobcat) man page. manpagefiles() em(bobcat/osharedstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(chmod)(1), bf(isharedstream)(3bobcat), bf(sharedblock)(3bobcat), bf(sharedmemory)(3bobcat) bf(sharedmutex)(3bobcat), bf(sharedpos)(3bobcat), bf(sharedsegment)(3bobcat), bf(sharedstream)(3bobcat), bf(sharedstreambuf)(3bobcat) manpagebugs() Note that by default exceptions thrown from within a bf(std::stream) object are caught by the stream object, setting its tt(ios::failbit) flag. To allow exceptions to leave a stream object, its tt(exceptions) member can be called, e.g., using: verb( myStream.exceptions(ios::failbit | ios::badbit | ios::eofbit); ) includefile(include/trailer) bobcat-3.19.01/documentation/man/irandstream.yo0000644000175000017500000000435212222576536020427 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::IRandStream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Random numbers istream) manpagename(FBB::IRandStream)(Istream producing random numbers) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::IRandStream) objects may be used to extract random numbers in a given range from a stream. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::istream), nl() bf(FBB::RandBuffer) (private) manpagesection(CONSTRUCTORS) itemization( itb(IRandStream(int max)) This bf(FBB::IRandStream()) constructor initializes the random generator. The default seed (i.e., 1) for the bf(srand)(3) function is used, meaning that every new run of the program will generate the same sequence of random values. Another constructor (see below) is provided when this is not considered appropriate. Random values between 1 and tt(max) (inclusive) are returned. itb(IRandStream(int min, int max)) This bf(FBB::IRandStream()) constructor initializes the random generator. The default seed (i.e., 1) for the bf(srand)(3) function is used, meaning that every new run of the program will generate the same sequence of random values. Another constructor (see below) is provided when this is not considered appropriate. Random values between tt(min) and tt(max) (inclusive) are returned. itb(IRandStream(int min, int max, int seed)) This bf(FBB::IRandStream()) constructor initializes the random generator. The seed is used to initialze the random number generator. To start the random generator at some unpredictable point, tt(time(0)) could be used. Random values between tt(min) and tt(max) (inclusive) are returned. ) manpagesection(INHERITED MEMBERS) Since the class uses public derivation from bf(std::istream), all members of this class can be used. manpagesection(EXAMPLE) verbinclude(../../irandstream/driver/driver.cc) manpagefiles() em(bobcat/irandstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(randbuffer)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/localsocketbase.yo0000644000175000017500000000456612222576536021263 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::LocalSocketBase)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz) (Base class for Unix Domain sockets) manpagename(FBB::LocalSocketBase) (Base class for Unix Domain socket-constructing classes) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() This class is a base class for the bf(FBB::LocalServerSocket) and bf(FBB::LocalClientSocket) classes. Since it is designed as a base class, its constructor is protected. All its remaining members are protected as well. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(PROTECTED CONSTRUCTOR) itemization( itb(LocalSocketBase()) The default constructor merely constructs a tt(FBB::LocalSocketBase) object. Before the object can be used, its tt(open()) member must be called first. itb(LocalSocketBase(string const &name)) This constructor creates a bf(LocalSocketBase) using the file specified in tt(name) as the Unix domain socket interface. If the socket could not be constructed, an bf(FBB::Exception) exception is thrown. ) The copy constructor is not available. manpagesection(PROTECTED MEMBER FUNCTIONS) itemization( itb(open(string const &name)) This member initiaizes a bf(LocalSocketBase) object following its construction using the default constructor. The file specified in tt(name) is used as the Unix domain socket interface. If the socket could not be constructed, an bf(FBB::Exception) exception is thrown. itb(size_t size() const) Accessor returning the size of the object's bf(sockaddr_un) (address) itb(int socket() const) This accessor returns the bf(FBB::LocalSocketBase)'s socket value. itb(sockaddr const *sockaddrPtr() const) Accessor returning the pointer to the object's bf(sockaddr). ) manpagesection(EXAMPLE) See the examples presented with the bf(localclientsocket)(3bobcat) and bf(localserversocket)(3bobcat) classes. manpagefiles() em(bobcat/localsocketbase) - defines the class interface manpageseealso() bf(bobcat)(7), bf(localclientsocket)(3bobcat), bf(localserversocket)(3bobcat), bf(socketbase)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/xpointer.yo0000644000175000017500000000474412224230116017752 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Xpointer)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Sets the X-pointer) manpagename(FBB::Xpointer)(Sets the location of the X-windows pointer) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat -lX11) manpagedescription() This class allows programs running within the X-graphical environment to set and retrieve the X-windows pointer location. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) itemization( itb(Xpointer()) The default constructor. Connects to the Display. throws an bf(Exception) exception if the display cannot be opened. With multiple bf(Xpointer) objects, the connection to the display is opened only once. This constructor throws an tt(Exception) exception if it could not connect to the Display. ) The copy constructor is available. manpagesection(MEMBER FUNCTIONS) itemization( itb(bool get(int *x, int *y) const) Returns in its arguments the currnet pointer coordinates relative to the root-window. On success tt(true) is returned; tt(false) is returned if the pointer could not be moved. itb(bool set(int x, int y) const) Sets the pointer to a location whose pixel coordinates are given with respect to the root-window. A negative x-coordinate is measured from the right screen-margin of the root window (going left), a negative y-coordinate is measured from the bottom screen-margin of the root window (going up). On success tt(true) is returned; tt(false) is returned if the pointer could not be moved. itb(void verify() const) Obsoleted, will be removed in a future Bobcat release. ) manpagesection(EXAMPLE) verb( #include #include #include using namespace FBB; int main() try { Xpointer xpointer; xpointer.verify(); if (!xpointer.set(100, 200)) throw string("Set pointer failed"); int x; int y; if (!xpointer.get(&x, &y)) throw string("Get pointer failed"); cout << "Pointer now at " << x << ", " << y << endl; return 0; } catch (string msg) { cout << msg << endl; return 1; } ) manpagefiles() em(bobcat/xpointer) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() Note that tt(-lX11) must be specified as well. includefile(include/trailer) bobcat-3.19.01/documentation/man/multistreambuf.yo0000644000175000017500000001520712222576536021162 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::MultiStreambuf)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Writing multiple streams) manpagename(FBB::MultiStreambuf)(Selectively writes multiple streams) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() The bf(FBB::MultiStreambuf) class is a specialization of bf(std::streambuf). It can be used to write selectvely to multiple bf(std::ostreams). Each bf(std::ostream) that is associated with an bf(FBB::MultiStreambuf) is given a mode-tag indicating whether the stream should always be used when information is inserted into the bf(FBB::MultiStreambuf), just once, or not at all. Each of the stream's mode-tags may be set to any of the defined tag-values. When the address of a bf(FBB::MultiStreambuf) is used to initialize a bf(std::ostream) the constructed bf(std::ostream) becomes an output-multiplexer: by inserting information into the bf(std::ostream) object, all bf(std::ostream) objects added to its bf(FBB::MultiStreambuf) buffer which have an active mode will receive that information. An bf(FBB::MultiStreambuf) object should be outlived by all active streams that are associated with it. No assumptions should be made about the order in which the bf(std::ostream) objects that are associated with the bf(FBB::MultiStreambuf) objects are visited when information is inserted. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(ENUMERATION) In the bf(Mode) enumeration the following values are defined: itemization( itb(OFF) A bf(std::ostream) having this mode will not be used when information is inserted into an bf(FBB::MultiStreambuf) itb(ON) A bf(std::ostream) having this mode will be used when information is inserted into an bf(FBB::MultiStreambuf) itb(ONCE) A bf(std::ostream) having this mode will be used once, until the next flushing operation, when information is inserted into an bf(FBB::MultiStreambuf) itb(RESET) A bf(std::ostream) having this mode will not be used when information is inserted into an bf(FBB::MultiStreambuf). At a flush operation all bf(ONCE) modes will be set to bf(RESET) ) manpagesection(TYPES) The following subtypes are defined in the class bf(FBB:MultiStreambuf): itemization( itb(iterator) This is a synonym of bf(std::vector::iterator) itb(const_iterator) This is a synonym of bf(std::vector::const_iterator) ) manpagesection(NESTED CLASS) The class bf(FBB::MultiStreambuf::stream) is defined as a nested class of bf(FBB::MultiStreambuf). It offers the following constructor and public members: itemization( itb(stream(std::ostream &os, Mode mode = ON)) The constructor stores a bf(std::ostream) object, and associates a bf(Mode) value with it. itb(void setMode(Mode mode)) This member is used to redefine the bf(stream)'s bf(Mode) value. itb(void mode() const) This member returns the bf(stream)'s bf(Mode) value. itb(operator std::ostream &()) This member returns the bf(stream)'s bf(std::ostream). ) manpagesection(CONSTRUCTORS) itemization( itb(MultiStreambuf()) The default constructor creates a bf(FBB::MultiStreambuf) object which contains no associated bf(std::ostream) objects. itb(MultiStreambuf(std::ostream &os, Mode mode = ON)) This constructor creates a bf(FBB::MultiStreambuf) object which is immediately associated with the bf(std::ostream) specified as its first argument. itb(MultiStreambuf(std::vector const &osvector)) This constructor creates a bf(FBB::MultiStreambuf) object which is immediately associated with all bf(std::ostream) objects that are stored in the bf(MultiStreambuf::stream) elements of the specified vector. ) The copy constructor is available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::ostringstream) and bf(std::exception) are available, as bf(FBB::MultiStreambuf) inherits from these classes. itemization( itb(iterator begin()) This member returns an iterator to the first bf(stream) element that is stored in a bf(FBB::MultiStreambuf) object. itb(const_iterator begin()) This member returns an iterator to the first (unmodifiable) bf(stream) element that is stored in a bf(FBB::MultiStreambuf) object. itb(iterator end()) This member returns an iterator pointing beyond the last bf(stream) element that is stored in a bf(FBB::MultiStreambuf) object. itb(iterator end()) This member returns an iterator pointing beyond the last (unmodifiable) bf(stream) element that is stored in a bf(FBB::MultiStreambuf) object. itb(void insert(std::ostream &os, Mode mode = ON)) This member adds the specified bf(std::ostream) using the specified bf(Mode) to the current set of bf(stream) objects. itb(void insert(std::vector const &os)) This member adds all bf(stream) objects stored in the bf(os) vector to the current set of bf(stream) objects. itb(void void setOnce()) This member will reset all the tt(RESET) bf(Mode) values of the stored bf(stream) objects to tt(ONCE). ) manpagesection(PROTECTED MEMBER FUNCTION) The member listed in this section implements the tasks of the comparably named virtual function in the class's private interface. This separates the redefinable interface from the user-interface. The class bf(MultiStreamBuf) can, in accordance with Liskov's Substitution Principle, be used as a tt(std:streambuf); but it also offers a facility for classes deriving from bf(MultiStreamBuf). This facility is listed here. itemization( itb(int pSync()) The contents of the bf(MultiStreamBuf)'s internal buffer is written to each of the tt(std::ostream) objects to which the bf(MultiStreamBuf) object has access. ) manpagesection(EXAMPLE) verb( #include #include #include using namespace std; using namespace FBB; int main() { MultiStreambuf msb(cout); ostream os(&msb); ofstream out("out"); msb.insert(out, MultiStreambuf::ONCE); os << "This is on cout and out" << endl; os << "This is on cout only" << endl; msb.setOnce(); os << "This is on cout and out" << endl; os << "This is on cout only" << endl; return 0; } ) manpagefiles() em(bobcat/multistreambuf) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/ofoldstream.yo0000644000175000017500000001506612222576536020441 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::OFoldStream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Fold long lines) manpagename(FBB::OFoldStream)(Folds long lines) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::OFoldStream) folds long lines written to it. The tt(OFoldStream) writes the (folded) lines to a second tt(ostream) which is either used by or opened by the tt(OFoldStream) object. tt(OFoldStream) objects never fold lines in the middle of series of non-blank characters but will always break a line at white space characters. The resulting lines will always appear to the right of a configurable left margin and to the left of a configurable right margin. There is a somewhat pathological exception to this: if a word is too long to fit in between the margins then the word will exceed the right hand margin. The indentation used for the left margins is configurable to either blanks (the default) or tabs. When tabs are used the width of a tab character is configurable, using a default of 8 positions in the destination stream. tt(OFoldStream) is implemented as a wrapper class around tt(std::ostream) and tt(FBB::OFoldStreambuf) and a more complete description of the folding process can be found in the bf(ofoldstreambuf)(3bobcat) man page. includefile(include/namespace) manpagesection(INHERITS FROM) std::ostream,nl() (and privately from FBB::OFoldStreambuf) manpagesection(ENUMERATION) The enumeration tt(TabsOrBlanks) is used to select tabs or blanks when writing the indentation. The default is blanks. When tabs are selected the display width of tabs characters can be configured as well (using the default of 8 positions for each tab-character. The enumeration has two values: itemization( itb(BLANKS) The default, indicating that the left margin is specified and written as a number of blanks; itb(TABS) Indicating that the left margin is specified and written as a number of tab-characters. ) The enumeration tt(TrailingBlanks) is used to configure the tt(OFoldStream) object with respect to any trailing blanks that may appear on the final line. It is the same enumeration type as used with tt(OFoldStreambuf) (cf. bf(ofoldstreambuf)(3bobcat)) having two values: itemization( itb(IGNORE_TRAILING_BLANKS) This indicates that trailing blanks appearing at the final line if it is not terminated by a newline should not be written to the destination tt(std::ostream). This is the default used by tt(OFoldStream) objects. itb(KEEP_TRAILING_BLANKS) This indicates that trailing blanks at the final line if it is not terminated by a newline should be written to the destination tt(std::ostream) ) manpagesection(CONSTRUCTORS) itemization( itb(OFoldStream()) This constructor initializes an tt(OFoldStream) object but does not associate it with a destination stream. It uses the values 0, 80, tt(BLANKS), and tt(IGNORE_TRAILING_BLANKS)for, resp. its left margin, right margin left-margin characters and tt(TrailingBlanks) handling mode. itb(OFoldStream(char const *fname, size_t leftIndent = 0, size_t rightMargin = 80, TabsOrBlanks tob = BLANKS, TrailingBlanks tb = IGNORE_TRAILING_BLANKS)) This constructor initializes an tt(OFoldStream) object and opens (using tt(std::ios::out)) the destination stream using the name specified as its tt(fname) argument. itb(OFoldStream(std::ostream &stream, size_t leftIndent = 0, size_t rightMargin = 80, TabsOrBlanks tob = BLANKS, TrailingBlanks tb = IGNORE_TRAILING_BLANKS)) This constructor initializes an tt(OFoldStream) object and uses as its destination stream the tt(std::ostream stream). ) The destructor writes any buffered information to the destination stream and will then flush the destination stream. manpagesection(MEMBER FUNCTIONS) All members of bf(std::ostream) are available, as bf(FBB::OFoldStream) inherits from this class. itemization( itb(void close()) This member flushes any pending information to the destination stream and then closes the destination stream. itb(void open(char const *fname, openmode mode = std::ios::out)) This member associates the tt(OFilterStream) object with an tt(std::ofstream) object whose filename is provided and that should receive the folded information. itb(void open(std::ostream &out)) This member associates the tt(OFilterStream) object with the provided tt(ostream) object. itb(void setMargins(size_t leftMargin, size_t rightMargin)) This member can be used to modify the left- and right folding margins. Note that the left margin may also be modified using the tt(FBB::lm) and tt(FBB::mlm) manipulators. itb(void setTrailingBlanks(TrailingBlanks tb)) This member can be used to modify the currently used tt(TrailingBlanks) parameter. itb(void useBlanks()) This member can be used to select blanks to be used when inserting left margins. itb(void useTabs(size_t tabWidth = 8)) This member can be used to select tab-characters to be used when inserting left margins. The second parameter is used to specify the display width of a tab-character. ) manpagesection(STATIC MEMBER FUNCTIONS) itemization( itb(size_t leftMargin(std::ostream const &os)) This member returns the current left margin setting of the tt(OFoldStream) object passed to it as its argument. The member defines a tt(std::ostream) parameter since in many cases the tt(OFoldStream) object will be used in functions themselves defining tt(std::ostream) parameters. Internally, the tt(std::ostream)'s tt(std::streambuf) is down cast to an tt(OFoldStreambuf) and an tt(FBB::Exception) exception is thrown if that cast fails. itb(size_t rightMargin(std::ostream const &os)) This member returns the current right margin setting of the tt(OFoldStream) object passed to it as its argument. The member's parameter is down cast in the same way as tt(leftMargin())'s argument: an tt(FBB::Exception) exception is thrown if that cast fails. ) manpagesection(EXAMPLE) verbinclude(../../ofoldstream/driver/driver.cc) manpagefiles() em(bobcat/ofoldstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(lm)(3bobcat), bf(mlm)(3bobcat), bf(ofoldstreambuf)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/syslogstream.yo0000644000175000017500000002714312222576536020655 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::SyslogStream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Output Stream for Syslog) manpagename(FBB::SyslogStream)(An output stream inserting syslog messages) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::SyslogStream) objects may be used as a tt(std::ostream) to write syslog messages using stream facilities. Multiple separate insertions can be used to create a single syslog message: the message is only sent to the syslog daemon after receiving a tt(flush) command (e.g., after inserting tt(std::flush) or tt(std::endl)). Non-printable characters (like tt('\n')) show up in the syslog message as octal values, preceded by tt(#) (e.g., tt(#012) for tt('\n')). The newline normally inserted by tt(std::endl) is ignored: bf(SyslogStream) objects interpret tt(std::endl) like tt(std::flush). One series of insertions may contain multiple tt(std::endl) or tt(std::flush) manipulators. At each of these manipulators a new message is sent to the syslog daemon, containing all info that has so far been buffered. After sending a message to the syslog daemon, the bf(SyslogStream)'s internal buffer is cleared. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::ostream) manpagesection(ENUMERATIONS) The following enumerations are defined in the namespace bf(FBB): bf(Priority): The values of this enumeration match the corresponding priority tt(LOG_xxx) values used with bf(syslog)(3): itemization( itb(EMERG) system is unusable; itb(ALERT) action must be taken immediately; itb(CRIT) critical conditions; itb(ERR) error conditions; itb(WARNING) warning conditions; itb(NOTICE) normal, but significant, condition; itb(INFO) informational message; itb(DEBUG) debug-level message; ) The tt(setMask) member (see below) can be used to select which type of messages will actually be processed by the syslog daemon. bf(PriorityType): This enumberation has two values fine-tuning the type of messages that are actually processed by the syslog daemon: itemization( itb(SINGLE) Only messages of the priority specified at the tt(setMask) call are processed by the syslog daemon; itb(UPTO) Messages of priority tt(EMERG) up to the the priority specified at the tt(setMask) call are processed by the syslog daemon; ) By default, the syslog daemon processes all messages it receives. bf(Facility): The values of this enumeration match the corresponding facility tt(LOG_xxx) values used with bf(syslog)(3): itemization( itb(AUTHPRIV) security/authorization messages (private) itb(CRON) clock daemon (tt(cron) and tt(at)) itb(DAEMON) other system daemons itb(KERN) kernel messages itb(LOCAL0) reserved for local use. bf(LOCAL1) through bf(LOCAL7) are available as well. itb(LPR) line printer subsystem itb(MAIL) mail subsystem itb(NEWS) tt(USENET) news subsystem itb(SYSLOGBUF) messages generated internally by tt(syslogbufd) itb(USER) generic user-level messages itb(UUCP) UUCP subsystem ) manpagesection(CONSTRUCTORS) itemization( itb(SyslogStream(string const &ident = "", FBB::Priority priority = FBB::NOTICE, FBB::Facility facility = FBB::USER, int option = 0)) This constructor initializes a bf(SyslogStream) object. The tt(ident) parameter is usually the name of the program. Its contents are prepended to syslog messages. The tt(priority) parameter determines the default importance of the message sent to the syslog daemon. By default messages are sent to the syslog daemon with priority bf(FBB::NOTICE). Syslog messages may be given different priority by inserting a bf(SyslogStream) manipulator (see below). The priority set at construction time may also be modified using the tt(setPriority) and tt(setDefaultPriority) members. Which messages actually appear in log facilities is not determined by the messages' priorities, but by syslog's em(log mask). The log mask can be set by the static member tt(setMask) (see below). The tt(facility) parameter determines the type of program doing the logging. By default bf(FBB::USER) is used. The tt(option) parameter may be used to specify various options (use the binary `tt(bitor)' (`tt(|)') operator to combine options): bf(LOG_CONS): write directly to system console if there is an error while sending to system logger nl() bf(LOG_NDELAY): open the connection immediately (normally, the con- nection is opened when the first message is logged) nl() bf(LOG_PERROR): print to stderr as well nl() bf(LOG__PID): include PID with each message nl() By default no options are used. itb(SyslogStream(char const *ident, FBB::Priority priority = FBB::NOTICE, FBB::Facility facility = FBB::USER, int option = 0)) This constructor is kept for backward compatibility. Its parameters have the same meanings as those of the abovementioned constructor. A tt(nullptr) indicates that no text needs to be prepended to syslog messages. ) Copy and move constructors are not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::ostream) are available, as bf(FBB::SyslogStream) inherits from this class. itemization( itb(void close()) If the bf(SyslogStream)'s internal buffer is not empty it is flushed to the syslog daemon. Thereafer bf(closelog)(3) is called. itb(Priority defaultPriority() const) Returns the current default priority. I.e., the priority that will be used for the messages after inserting tt(endl) or tt(flush). itb(void open(string const &ident, FBB::Priority priority = FBB::NOTICE, FBB::Facility facility = FBB::USER, int option = 0)) Redefines the current identifier, priority, facility and options that are used when sending messages to the syslog daemon. If the bf(SyslogStream)'s internal buffer is not empty it is first flushed to the syslog daemon using the identifier, priority and options that were active just before calling tt(open). itb(Priority priority() const) Returns the next priority. I.e., the priority that will be used for the next message that is sent to the syslog daemon. itb(Priority setDefaultPriority(Priority priority)) Changes the default priority of the next message that is sent to the syslog daemon after inserting tt(std::eoln) or tt(std::flush). The previously active default priority is returned. itb(Priority setPriority(Priority priority)) Changes the priority for the next message that is sent to the syslog daemon after inserting tt(std::eoln) or tt(std::flush). Subsequent messages will again use the default priority. The previously active priority setting is returned. ) manpagesection(STATIC MEMBER FUNCTIONS) itemization( itb(Priority setMask(Priority priority, PriorityMask upTo)) Syslog messages of (if tt(upTo) equals tt(SINGLE)) or up to (if tt(upTo) equals tt(UPTO)) the indicated priority are processed by the syslog daemon. itb(Priority setMask(Priority priority, Priority ...priorities)) Syslog messages of the priorities passed to tt(setMask) are processed by the syslog daemon. At least one priority must be specified. itb(Facility stoF(std::string const &name, Facility facility = USER)) Returns the facility matching the name of the facility provided by tt(name). Facility matching is performed case insensitively. E.g., if tt(name) contains tt(daemon), facility tt(FBB::DAEMON) is returned. If tt(name) does not match any facility name then the value of this function's second argument is returned. The function's name (tt(stoF)) was used in analogy of the various tt(sto...) conversion functions that were made available by the bf(C++11) standard. itb(Priority stoP(std::string const &name, Priority priority = NOTICE)) Returns the priority matching the name of the priority provided by tt(name). Priority matching is performed case insensitively. E.g., if tt(name) contains tt(emerg), priority tt(FBB::EMERG) is returned. If tt(name) does not match any priority name then the value of this function's second argument is returned. The function's name (tt(stoP)) was used in analogy of the various tt(sto...) conversion functions that were made available by the bf(C++11) standard. ) manpagesection(MANIPULATORS) The following set of manipulators are all defined as (static) members. They may be inserted into an bf(FBB::SyslogStream) object. Except for the last manipulator (tt(strerrno)), they have the following characteristics in common: itemization( it() They change the priority of the messages that are subsequently inserted by the bf(FBB::SyslogStream) object, thus acting like a separate tt(setPriority) call. it() When inserting multiple manipulators before the inserted message is flushed (e.g., using the tt(std::flush) or the tt(std::endl) manipulators) the last inserted bf(FBB::SyslogStream) manipulator will be used. it() If the manipulators are not inserted into an bf(FBB::SyslogStream) object (but in another tt(std::ostream) type of object) then they perform no action. ) Here are the available manipulators: itemization( itb(SyslogStream::alert) Messages are inserted with priority bf(FBB::ALERT). itb(SyslogStream::crit) Message are inserted with priority bf(FBB::CRIT). itb(SyslogStream::debug) Messages are inserted with priority bf(FBB::DEBUG). itb(SyslogStream::emerg) Messages are inserted with priority bf(FBB::EMERG). itb(SyslogStream::err) Messages are inserted with priority bf(FBB::ERR). itb(SyslogStream::info) Messages are inserted with priority bf(FBB::INFO). itb(SyslogStream::notice) Messages are inserted with priority bf(FBB::NOTICE). itb(SyslogStream::strerrno) This manipulator inserts the textual interpretation of tt(std::errno)'s current value into a tt(std::ostream). Note that, different from the other manipulators, the object into which this manipulator is inserted does not have to be a bf(FBB::SyslogStream) object. itb(SyslogStream::warning) Messages are inserted with priority bf(FBB::WARNING). ) manpagesection(EXAMPLE) verb( #include using namespace std; using namespace FBB; int main(int argc, char **argv) { SyslogStream sls(argv[0]); sls << SyslogStream::debug << "Hello world" << flush << SyslogStream::strerrno << endl; } ) manpagefiles() em(bobcat/syslogstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(closelog)(3), bf(openlog)(3), bf(rsyslogd)(8), bf(syslog)(3), bf(syslogbuf)(3bobcat) manpagebugs() The constructor's tt(option) parameter is an tt(int). Because of this, tt(int) values rather than enumeration values are passed to the constructor. It is the responsibility of the programmer to pass defined option values only. includefile(include/trailer) bobcat-3.19.01/documentation/man/a2x.yo0000644000175000017500000001177012222576536016612 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::A2x)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Error handler) manpagename(FBB::A2x)(Objects performing ascii-to-x (anything) conversions) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::A2x) objects offer the bf(C++) equivalent of the standard bf(C) conversion functions bf(atoi)(3), bf(atol)(3), bf(atof)(3) etc. tt(A2x) objects generalize these bf(C) functions to em(any) type that can be extracted from an bf(istream) object. Since bf(FBB::A2x) represents the object-variant of the bf(C) functions, and is therefore em(type-safe) and em(extensible), their use is greatly preferred over using the standard bf(C) functions. manpagesection(NAMESPACE) bf(FBB)nl() All constructors, members, and operators, mentioned in this man-page, are defined in the namespace bf(FBB). manpagesection(INHERITS FROM) bf(std::istringstream) manpagesection(CONSTRUCTORS) itemization( itb(A2x()) This constructor constructs an empty tt(A2x) object. No information can be converted from a thus constructed tt(A2x) object. itb(A2x(char const *text)) This constructor stores tt(text). If tt(text) represents a textual value of some type, the tt(A2x) object may be used to initialize or assign this value to a variable of that particular type. Extraction, however is also still possible. itb(A2x(std::string const &str)) This constructor stores the text contained in tt(str). If this text represents a textual value of some type, the tt(A2x) object may be used to initialize or assign this value to a variable of that particular type. Extraction is also still possible. ) The copy constructor is available. manpagesection(STATIC MEMBER FUNCTION) itemization( itb(bool lastFail()) This member returns tt(true) if the last conversion failed (i.e., the object's tt(fail()) member returned tt(true) and returns tt(false) otherwise). This member allows checks on the success of the extraction/conversion using anonymous tt(A2x) objects. The member also returns tt(true) when no conversions have as yet been performed.nl() Note that this member is a thread-unsafe em(static) member: in a multithreaded program locks may be required to ensure that the proper conversion result is inspected. ) manpagesection(MEMBER FUNCTION) All members of the bf(istringstream) class are available. itemization( itb(Type to()) This member returns any type tt(Type) supporting extractions from tt(i[string]streams). If the extraction fails, the tt(A2x) object's tt(good()) member will return tt(false), and the tt(Type)'s default value is returned. This operator was implemented as a template member function. There is also a type conversion operator available (see below), but the member function variant may be preferred over the conversion operator in situations where explicit disambiguation is required (e.g., in cases where a conversion has no obvious type solution such as direct insertions) An example is provided in the bf(EXAMPLE) section below. ) manpagesection(OVERLOADED OPERATORS) itemization( itb(operator Type()) Conversion to any type tt(Type) supporting extractions from tt(i[string]streams). If the extraction fails, the tt(A2x) object's tt(good()) member will return tt(false), and the tt(Type)'s default value is returned. This operator was implemented as a template member function. itb(istream &operator>>(istream &, Type &)) Extraction to any type tt(Type) supporting extractions from tt(i[string]streams). If the extraction fails, the tt(A2x) object's tt(good()) member will return tt(false), and the tt(Type)'s default value is returned (this facility is implied by the fact that this class inherits from bf(istringstream), but it's probably useful to stress that the extraction operation is still available). itb(A2x &operator=(char const *)) Stores new text in the tt(A2x) object, resets the status flags to tt(ios::good). If a 0-pointer is passed, an empty string is stored. itb(A2x &operator=(std::string const &)) Stores the text stored in the tt(std::string) argument in the tt(A2x) object, resets the status flags to tt(ios::good). itb(A2x &operator=(A2x const &)) The standard overloaded assignment operator is available ) manpagesection(EXAMPLE) verb( int x = A2x("12"); A2x a2x("12.50"); double d; d = a2x; a2x = "err"; d = a2x; // d now 0 a2x = " a"; char c = a2x; // c now 'a' // explicit conversion to `double' cout << A2x("12.4").to() << endl; ) manpagefiles() em(bobcat/a2x) - defines the class interface manpageseealso() bf(bobcat)(7), bf(x2a)(3bobcat), bf(atoi)(3), bf(atol)(3), bf(atof)(3), bf(strtod)(3), bf(strtol)(3), bf(strdoul)(3) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/align.yo0000644000175000017500000000576412222576536017220 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Align)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Table Element Alignment) manpagename(FBB::Align)(Class used to align elements in Table objects) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() This class defines the objects used by the bf(FBB::Table) to define the alignment of its columns and/or elements. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ADDITIONAL TYPEDEF) The type bf(FBB::Manipulator) can be used as a shorthand for verb( std::ios_base &(*)(std::ios_base &) ) which is the prototype of a standard io-manipulator like tt(std::left). manpagesection(CONSTRUCTORS) itemization( itb(Align(size_t column = 0, Manipulator manip = std::right)) This constructor defines the alignment of column tt([column]) of a bf(Table) object. When it is used, it is the responsibility of the programmer to ensure that the indicated bf(Table) column exists. This constructor can also be used as a default constructor, defining a default right-alignment. itb(Align(int row, size_t column, Manipulator manip)) This constructor defines the alignment of element tt([row][column]) of a bf(Table) object. When it is used, it is the responsibility of the programmer to ensure that the indicated bf(Table) element exists. itb(Align(Manipulator manip)) This constructor is used to initialize the object with a specified alignment type. ) The copy constructor is available. manpagesection(OVERLOADED OPERATORS) itemization( itb(operator size_t() const) Returns the value representing a requested width of an element in a bf(Table) object. ) manpagesection(MEMBER FUNCTIONS) itemization( itb(size_t col() const) Returns the object's column index. itb(bool hasRow() const) Returns tt(true) if the object's bf(row()) member returns a sensible value. itb(size_t row() const) Returns the object's row index. itb(Manipulator manip() const) Returns the bf(Manipulator) stored in the object. itb(void setWidth(size_t width)) Assigns a value to the field-width stored in the object. itb(void setManip(Manipulator manip)) Changes the object's currently stored bf(Manipulator). ) manpagesection(MANIPULATORS) The following manipulator (which is em(not) part of the bf(FBB::Align), class), is defined in the bf(FBB) namespace. It can be stored in bf(Align) objects and is used by tt(Table) objects: itemization( itb(FBB::center) ) manpagesection(EXAMPLE) See the bf(table)(3bobcat) man-page. manpagefiles() em(bobcat/align) - defines the class interface manpageseealso() bf(bobcat)(7), bf(manipulator)(3bobcat), bf(table)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/localserversocket.yo0000644000175000017500000001714412222576536021653 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::LocalServerSocket)(3bobcat) (_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Unix Domain Server Socket) manpagename(FBB::LocalServerSocket) (Unix Domain Server socket accepting connection requests) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() An bf(FBB::LocalServerSocket) defines a Unix Domain server socket, listening for connection requests from the local host using a Unix Domain socket. Connection requests may be accepted in either em(blocking) or em(non-blocking) modes. When a connection is accepted a socket is returned which may be used to read information from or write information to the client requesting the connection. The socket that is made available is a em(file descriptor) which may be used to initialize a bf(std::istream) and/or bf(std::ostream). The bf(std::istream) is used to read information from the client process; the bf(std::ostream) is used to send information to the client process. Since a socket may be considered a em(file descriptor) the avaiable bf(FBB::IFdStream), bf(FBB::IFdStreamBuf), bf(FBB::OFdStream), and bf(FBB::OFdStreamBuf) classes may be used profitably here. Note that having available a socket does not mean that this defines the communication protocol. It is (still) the responsibility of the programmer to comply with an existing protocol or to implement a tailor-made protocol. The latter situation implies that the sequence of input- and output operations is defined by the programmer. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::LocalSocketBase) manpagesection(ENUMERATION) The following enumeration is defined in th class bf(FBB::LocalServerSocket): bf(enum Socket)nl() This enumeration holds two values: itemization( itb(KEEP) When this value is specified at construction time, the file representing the Unix Domain Socket will not be removed when the bf(LocalServerSocket) is destroyed. This is the default value used with the bf(LocalServerSocket) constructor. itb(UNLINK) When this value is specified at construction time, the file representing the Unix Domain Socket will be removed when the bf(LocalServerSocket) is destroyed. ) manpagesection(CONSTRUCTOR) itemization( itb(LocalServerSocket()) This constructor creates an empty (non-functioning) tt(FBB::LocalServerSocket) object. Before it can be used, the tt(open()) member must be called (see below). itb(LocalServerSocket(string const &name, Socket action = KEEP) throw (Exception)) This constructor initializes an bf(FBB::LocalServerSocket) object, which will listen for connection requests using the named Unix Domain socket. An bf(FBB::Exception) is thrown if the socket could not be constructed. If the constructor is given a second argument tt(FBB::LocalServerSocket::UNLINK), the constructed socket will be unlinked when the bf(FBB::LocalServerSocket) object is destroyed. The construction of the socket does not mean that the bf(FBB::LocalServerSocket) object is actually listening for connections. To start listening, the member bf(listen()) should be called. ) The copy constructor is not available. manpagesection(MEMBER FUNCTIONS) itemization( itb(size_t accept()) The bf(accept()) member returns an tt(size_t) which is a file descriptor (socket) that may be used to communicate with the client requesting the connection. In more complex programs the returned file descriptor (socket) could be passed to a class derived from bf(FBB::Fork), handling the communication with the child as a separate (child) process. itb(void listen(size_t backlog = 5, bool blocking = true)) The bf(listen()) member defines the way the bf(FBB::LocalServerSocket) will listen for clients requesting a connection. It can be used only once with a bf(FBB::LocalServerSocket). An bf(FBB::Exception) object is thrown if listening fails. The bf(listen()) member's tt(backlog) parameter defines the size of the bf(FBB::LocalServerSocket)'s internal queue in which connection requests may be stored waiting for their turn to be serviced. When tt(backlog) requests are waiting and another request arrives, then that request is lost. The member's second parameter, tt(blocking), is used to control the blocking mode. By default, blocking is used, and tt(listen()) will wait until a connection is established. This is ok in situations where clients connect infrquently and for relatively short time intervals. Otherwise, in more complex programs, an bf(FBB::Selector) object can be used to sense input on the server socket and/or on various client sockets. itb(void open(string const &name, Socket action = KEEP)) This member prepares a bf(FBB::LocalServerSocket) object for use. It should only be used in combination with the default constructor. Following tt(open()) the tt(FBB:::LocalServerSocket) object will be able to listen for connection requests using the named Unix Domain socket. An bf(FBB::Exception) is thrown if the socket could not be constructed. If the a second argument tt(FBB::LocalServerSocket::UNLINK), is provided the constructed socket will be unlinked when the bf(FBB::LocalServerSocket) object is destroyed. The construction of the socket does not mean that the bf(FBB::LocalServerSocket) object is actually listening for connections. To start listening, the member bf(listen()) should be called next. ) manpagesection(EXAMPLE) See also the bf(localclientsocket)(3bobcat) example. verb( #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) { cerr << "Provide local filename, e.g., /tmp/uds\n"; return 1; } LocalServerSocket server(argv[1]); cerr << "server using `" << argv[1] << "'" << endl; cout << "The server terminates when it receives a single `q' on a line\n" "A connection is terminated when no input is received anymore.\n" "Then another connection is possible" << endl; server.listen(); // listen in blocking mode while (true) { int fd = server.accept(); cerr << "Client FD = " << fd << ", " << endl; IFdStream in(fd); // stream to read from client OFdStream out(fd); // stream to write to client string cmd; while (getline(in, cmd)) { cout << "Got: " << cmd << endl; out << "Got: " << cmd << "\r" << endl; if (cmd[0] == 'q') return 0; } cout << "Ready for another connection\n"; } } catch (Exception const &err) { cerr << err.what() << endl << "Server socket on port " << argv[1] << " can't be opened" << endl; return -1; } ) manpagefiles() em(bobcat/serversocket) - defines the class interface manpageseealso() bf(bobcat)(7), bf(localclientsocket)(3bobcat), bf(fork)(3bobcat), bf(ifdstream)(3bobcat), bf(ifdstreambuf)(3bobcat), bf(localsocketbase)(3bobcat), bf(ofdstream)(3bobcat), bf(ofdstream)(3bobcat), bf(select)(2), bf(selector)(3bobcat), bf(serversocket)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/glob.yo0000644000175000017500000001072312222576536017040 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Glob)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Files matching a pattern) manpagename(FBB::Glob) (Wrapper around bf(glob)(3) to find files matching a pattern) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() The bf(FBB::Glob) class is a wrapper around the bf(C) function bf(glob)(3). It returns a list of files matching a certain pattern provided to bf(FBB::Glob)'s constructors or members. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ENUMERATIONS) bf(Glob::Type): nl() This enumeration, which is identical to the bf(stat)(3bobcat) tt(Type) enumeration), defines the following values: includefile(gs.inc) bf(Glob::Flags): itemization( itt(ERR): Return on read errors; itt(MARK): Append a slash to each name. itt(NOSORT): Don't sort the names. itt(NOESCAPE): Backslashes don't quote metacharacters. itt(PERIOD): Leading tt(.)-characters can be matched by metachars (i.e., tt(*) and tt(?)). ) bf(Glob::Dots): itemization( itt(FIRST): Filenames starting with a dot will be listed first. Within this set and in the leftover-set the relative ordering is maintained. itt(DEFAULT): Return filenames as they appear in the globbing process. ) manpagesection(CONSTRUCTORS) itemization( itb(Glob(std::string const &pattern = "*", int flags = PERIOD, Dots dots = FIRST)) This constructor (which can also be used as the default constructor) determines all elements matching tt(pattern). An tt(Exception) exception is thrown if the constructor could not properly complete it tasks. Multiple flags may be specified, separated by the tt(bitor) operator. This constructor properly completes its task if only defined bf(Flag) values were specified and if the bf(glob)(3) function returned without errors. itb(Glob(Type type, std::string const &pattern = "*", int flags = PERIOD, Dots dots = FIRST)) This constructor determines all elements of tt(pattern) matching tt(Type). The specified tt(type) value may consist of any tt(bitor)-ed combination of enum values defined by the tt(Type) enum. Remaining parameters and ) tt(Glob) offers copy and move constructors. manpagesection(OVERLOADED OPERATORS) itemization( itb(Glob &operator=(Glob const &other)) The assignment operator is available. itb(Glob &operator=(Glob &&tmp)) The move-assignment operator is available. itb(char const *operator[](size_t idx) const) The element at index position tt(idx) is returns as a bf(C) string. It returns an empty string if tt(idx) is or exceeds bf(size()). ) manpagesection(MEMBER FUNCTIONS) itemization( itb(void verify() const) Empty function, kept for backward compatibility. itb(size_t size() const) Returns the number of elements that were detected. itb(char const *const *begin() const) Returns a pointer to the first element that was detected. This pointer can be used in generic algorithms as an output-iterator supporting pointer arithmetic. itb(char const *const *end() const) Returns a pointer beyond the last element that was detected. This pointer can be used in generic algorithms as an output-iterator supporting pointer arithmetic. itb(void swap(Glob &other)) Swaps the contents of the other object with the current object. ) manpagesection(EXAMPLES) verb( int main(int argc, char **argv) { if (argc == 1) { cout << "Provide glob-expression as 1st arg\n"; return 1; } cout << "General:\n"; Glob general; for (size_t idx = 0; idx < general.size(); idx++) cout << idx << ": " << general[idx] << endl; cout << "Pattern: " << argv[1] << "\n"; Glob pattern(argv[1], Glob::PERIOD, Glob::DEFAULT); for (size_t idx = 0; idx < pattern.size(); idx++) cout << idx << ": " << pattern[idx] << endl; return 0; } ) manpagefiles() em(bobcat/glob) - defines the class interface manpageseealso() bf(bobcat)(7), bf(stat)(3bobcat), bf(glob)(3) manpagebugs() No Reported Bugs. includefile(include/trailer) bobcat-3.19.01/documentation/man/mstream.yo0000644000175000017500000003204512222576536017566 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Mstream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Message handler) manpagename(FBB::Mstream)(Generic message handling stream) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() Objects of this class may be used to handle messages in a standardized way. Messages may be prefixed with order numbers and labels and/or line numbers. Messages generated by tt(Mstream) objects may optionally end in an exception, allowing simple implementation of, e.g., fatal error messages. Four message streams are provided by the tt(BOBCAT) library and may be used after including the tt(mstream) header file. They are all defined in the tt(FBB) namespace: itemization( itt(FBB::emsg) for generating standard (labeled and numbered) error messages, e.g. verb( [Error 1] this is an error message ) itt(FBB::fmsg) for generating (labeled) fatal error messages, ending in an exception, e.g., verb( [Fatal] this fatal message is followed by an exception ) itt(FBB::imsg) for generating plain informational messages, e.g., verb( this is a plain message ) itt(FBB::wmsg) for generating (labeled) warning messages; verb( [Warning] this is a warning ) ) By default all messages are inserted into the standard output stream, but other destinations (standard error, a named file, etc.) can easily be configured. tt(Mstream) objects themselves are tt(std::ostream) objects, so they can be used as objects passed to functions expecting tt(ostream) arguments. Messages inserted into tt(Mstream) objects are buffered until the buffer is flushed by their tt(std::ostream) parts or when either the tt(FBB::endl) or tt(FBB::flush) is inserted into the message stream. Since these manipulators act like tt(std::endl) and tt(std::flush) when inserted into another kind of tt(std::ostream) object, tt(using FBB::endl) and tt(using FBB::flush) might be worth considering. Also, when tt(using namespace std) em(and) tt(using namespace FBB) is specified the tt(FBB::endl) and tt(FBB::flush) manipulator will automatically be used with tt(Mstream) objects. Messages inserted into tt(Mstream) objects are considered completed at the insertion of the tt(FBB::endl) or tt(FBB::flush) manipulators. Message labels, line number labels and line numbers will only be shown for the next line after these manipulators have been inserted and exceptions are, if needed, thrown from these manipulators. manpagesection(NAMESPACE) bf(FBB)nl() All elements mentioned in this man-page, are defined in the namespace bf(FBB). manpagesection(INHERITS FROM) bf(std::ostream) manpagesection(CONSTRUCTORS) itemization( itb(Mstream()) The default constructor generates messages using the tt(std::streambuf) used by tt(std::cout). There is no limit to the number of messages that may be inserted. No message or line numbers are shown, no exception are thrown when inserting messages. itb(explicit Mstream(std::ostream &ostr, size_t maxCount = std::numeric_limits::max(), std::string const &tag = "", bool throwing = false)) This constructor uses the tt(std::streambuf) that is also used by the tt(ostream ostr). By default (using the default argument values) there is no limit to the number of messages that may be inserted. No message or line numbers are shown, no exception are thrown when inserting messages. Specifying any other value than tt(std::numeric_limits::max()) will set the maximum number of messages that can be inserted to that value. The tt(tag) defines the text of the message label (e.g., tt(Error)). When tt(throwing) is specified as tt(true) an tt(FBB::Exception) exception is thrown after completing a message. The generated exception holds the id (see below for the member tt(id)) of the tt(Mstream) object from which the exception was thrown as well as the text tt(FBB::Mstream). itb(explicit Mstream(std::streambuf &buf, size_t maxCount = std::numeric_limits::max(), std::string const &tag = "", bool throwing = false)) This constructor uses tt(buf) to insert messages into. The remaining parameters are identical to those of the previous constructor. itb(explicit Mstream(std::string const &name, size_t maxCount = std::numeric_limits::max(), std::string const &tag = "", bool throwing = false)) This constructor creates a tt(std::ofstream) from the provided tt(name) parameter. It throws an tt(FBB::Exception) exception if the stream cannot be opened for writing. If a file by that name already exists it is rewritten. The remaining parameters are identical to those of the previous two constructors. ) As tt(Mstream) inherits from tt(std::ostream) the copy constructor is not available. Neither is the move constructor. manpagesection(MEMBER FUNCTIONS) itemization( itb(size_t count() const) returns the number of inserted messages (if tt(setCount) has been called: the value set by the last tt(setCount) call plus the number of inserted messages since that call). itb(bool isActive() const) returns tt(true) if messages can actually be inserted into the bf(FBB::MStream) object, and tt(false) if inserted messages are ignored. When ignoring messages the message count is not updated. itb(int id() const) returns the unique em(id) of the tt(Mstream) object. itb(bool lineExcess() const) returns bf(true) after attempting to insert an additional message after tt(maxCount) number of messages have been inserted. itb(std::string const &lineTag() const) returns the currently used line-tag (by default `tt(Line)'). itb(size_t maxCount() const) returns the maximum number of messages that can be inserted. If the returned value equals tt(std::numeric_limits::max()) then there is no limit to the number of messages that can be inserted. itb(void noLineNr()) calling this member will suppress the display of a line number if it is called after calling tt(setLineNr) (see below) but before a message is being (or has been) inserted. itb(void off()) after calling tt(off) messages inserted into the tt(Mstream) object are silently ignored. After calling tt(off) the internal message counter is not incremented when messages are inserted. itb(void on()) by default and after calling tt(on) messages inserted into the tt(Mstream) object are sent to their destination stream. itb(void reset(std::ostream &ostr)) messages inserted into the tt(Mstream) object are handled by the tt(std::streambuf) also used by tt(ostr). Other parameters (e.g., tt(maxCount), the message label) are kept as-is. itb(void reset(std::streambuf *buf)) messages inserted into the tt(Mstream) object are handled by tt(std::streambuf buf). Other parameters (e.g., tt(maxCount), the message label) are kept as-is. itb(void reset(FBB::Mstream const &mstream)) the current object is reset using the parameters of the tt(mstream) parameter. itb(void reset(std::string const &name, size_t maxCount, std::string const &tag, bool throwing)) messages inserted into tt(Mstream) objects are handled by a tt(std::ofstream) created using the provided tt(name) parameter. tt(FBB::Exception) exception if the stream cannot be opened for writing. If a file by that name already exists it is rewritten. Other parameters (e.g., tt(maxCount), the message label) are kept as-is. itb(void reset(std::ostream &ostr, size_t maxCount, std::string const &tag, bool throwing)) messages inserted into tt(Mstream) objects are handled by the tt(std::streambuf) also used by tt(ostr). By specifying tt(std::numeric_limits::max()) for tt(maxCount) there is no limit to the number of messages that may be handled by this tt(std::streambuf). The tt(tag) defines the text of the message label (e.g., tt(Error) or the empty string for no message label). When tt(throwing) is specified as tt(true) an tt(FBB::Exception) exception is thrown after completing a message. itb(void reset(std::streambuf *buf, size_t maxCount, std::string const &tag, bool throwing)) messages inserted into tt(Mstream) objects are handled by tt(std::streambuf buf). The remaining parameters are identical to those of the previous tt(reset) member. itb(void reset(std::string const &name, size_t maxCount, std::string const &tag, bool throwing)) messages inserted into tt(Mstream) objects are handled by a tt(std::ofstream) created using the provided tt(name) parameter. It throws an tt(FBB::Exception) exception if the stream cannot be opened for writing. If a file by that name already exists it is rewritten. The remaining parameters are identical to those of the previous two tt(reset) members. itb(void reset(FBB::Mstream const &mstream)) the current object is reset using the parameters of the tt(mstream) parameter. Following the reset all of the current object's parameters can independently be modified from those used by tt(mstream). itb(bool setActive(bool ifTrue)) If tt(ifTrue) equals tt(true) the tt(Mstream) is activated otherwise its actions are suppressed. Returns tt(ifTrue). itb(void setCount(size_t count)) assigns the value tt(count) to the object's message counter. itb(void setLineNr(size_t lineNr)) specifies the value tt(lineNr) as the message's line number when the next line is displayed (see also tt(noLineNr)). This value is em(not) changed by the tt(Mstream) object. To display another line number the member will have to be called again (i.e., the line number is not displayed automatically again at every new line). itb(void setLineTag(std::string const &tag)) specifies the tag prefixing line numbers. By default the line tag equals `tt(Line)'. itb(void setMaxCount(size_t maxCount)) defines tt(maxCount) as the maximum number of messages that can be inserted into the tt(Mstream) object. itb(void setTag(std::string const &tag)) specifies the tag prefixing messages. By default the tag is empty. If not empty the tag is enclosed by square brackets. E.g., specifying the tag `tt(Error)' will prefix messages with tt([Error]). itb(std::string const &tag() const) returns the currently used message tag (by default an empty string). itb(bool throws()) returns tt(true) when the tt(Mstream) object will throw an tt(FBB::Exception) exception at the next completed message. The generated exception holds the id (see earlier for the member tt(id)) of the tt(Mstream) object from which the exception was thrown as well as the text tt(FBB::Mstream). itb(void throwing(bool ifTrue)) modifies the behaviro of tt(Mstream) objects at completed messages. After passing tt(true) tt(Mstream) objects will throw an tt(FBB::Exception) exception at the next completed message, otherwise this exception is not thrown. The generated exception holds the id (see earlier for the member tt(id)) of the tt(Mstream) object from which the exception was thrown as well as the text tt(FBB::Mstream). ) manpagesection(MANIPULATORS) Note that the following two manipulators are not members of the class bf(Mstream), but are free functions defined in the namespace bf(FBB). itemization( itb(std::ostream &endl(std::ostream &out)) This manipulator inserts a newline character in the tt(Mstream)'s stream and then calls tt(FBB::flush). This manipulator acts like tt(std::endl) and tt(std::flush) when inserted into another kind of tt(std::ostream) object. itb(std::ostream &flush(std::ostream &out)) This manipulator completes the message that is currently being inserted into an tt(Mstream) object. It flushes the object's destination stream and prepares the object for the next message. When the object's tt(throws) member returns tt(true) it will throw an tt(FBB:::Exception) exception which holds the id (see earlier for the member tt(id)) of the tt(Mstream) object from which the exception was thrown as well as the text tt(FBB::Mstream). When used in combination with another kind of tt(std::ostream) object it acts like tt(std::flush). ) As the manipulators tt(FBB::endl) and tt(FBB::flush) act like, respectively, tt(std::endl) and tt(std::flush) when inserted into another kind of tt(std::ostream) object, using the declarations `tt(using FBB::endl)' and `tt(using FBB::flush)' might be worth considering. Also, when tt(using namespace std) em(and) tt(using namespace FBB) is specified the tt(FBB::endl) and tt(FBB::flush) manipulator will automatically be called when inserting tt(endl) or tt(flush) into tt(Mstream) objects. manpagesection(EXAMPLE) verbinclude(../../mstream/driver/driver.cc) manpagefiles() em(bobcat/mstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(errno)(3bobcat), bf(mbuf)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/ifdstream.yo0000644000175000017500000000365012222576536020074 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::IFdStream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (File Descriptor Input Stream) manpagename(FBB::Ifdstream)(Input Stream initialized by a File Descriptor) manpagesynopsis() bf(#include )nl() manpagedescription() bf(FBB::IFdStream) objects may be used to extract information from a device whose file descriptor is available. File descriptors are not defined within the context of bf(C++), but they can be used on operating systems that support the concept. Realize that using file descriptors introduces operating system dependencies. Note that em(sockets) can be used as file descriptors. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::istream) manpagesection(CONSTRUCTORS) itemization( itb(IFdStream(int fd, size_t n = 1)) The constructor initializes the object to read from descriptor tt(fd), using a buffer of size tt(n), by default having size 1. ) The copy constructor is not available. manpagesection(MEMBER FUNCTIONS) All members of bf(std::istream) are available, as bf(FBB::IFdStream) inherits from this class. There are no additional members. manpagesection(EXAMPLE) See the bf(clientsocket)(3bobcat) man-page for an example showing how to use tt(IFdStream). manpagefiles() em(bobcat/ifdstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ifdstreambuf)(3bobcat), bf(ofdstream)(3bobcat) manpagebugs() The tt(IFdStream) object uses a tt(IFdStreamBuf) for its tt(std::streambuf). This buffer is associated with the file descriptor passed to tt(IFdStream)'s constructor. When the tt(IFdStream) object goes out of scope the device (file, socket, etc.) to which the file descriptor that was passed to tt(IFdStream)'s constructor is em(not) closed. includefile(include/trailer) bobcat-3.19.01/documentation/man/ofdstreambuf.yo0000644000175000017500000001332712222576536020601 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::OFdStreambuf)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (File Descriptor Output Stream Buffer) manpagename(FBB::OFdStreambuf) (Output stream buffer initialized by a file descriptor) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::OFdStreambuf) objects may be used as a bf(std::streambuf) of tt(std::ostream) objects to allow insertions into a file descriptor. File descriptors are not defined within the context of bf(C++), but they can be used on operating systems that support the concept. Realize that using file descriptors introduces operating system dependencies. includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(ENUMERATION) The public enumeration bf(Mode) defined in the class bf(FBB::OFdStreamBuf) has the following values: itemization( it() bf(CLOSE_FD), indicating that the file descriptor used by the object must be closed; it() bf(KEEP_FD) (the default) indicating that the file descriptor used by the object must not be closed. ) manpagesection(CONSTRUCTORS) itemization( itb(OFdStreambuf()) This constructor initializes the streambuf, without associating it to a file descriptor, and without using buffering. The member bf(open()) can be used to associate the object later on with a file descriptor and optionally a buffer size. When the object is destroyed or if the mode-less overloaded version of the bf(open) member is called, the file descriptor will be closed. itb(OFdStreambuf(Mode mode)) This constructor initializes the streambuf, without associating it to a file descriptor, and without using buffering. The member bf(open()) can be used to associate the object later on with a file descriptor and optionally a buffer size. When the object is destroyed or if the mode-less overloaded version of the bf(open) member is called, the bf(Mode) argument determines whether the file descriptor will be closed or will remain open. itb(OFdStreambuf(int fd, size_t n = 1)) This constructor initializes the streambuf, associating it to file descriptor tt(fd), and an optional unget buffer size (by default having size 1). When bf(open) is called subsequently, or if the object is destroyed the provided file descriptor will be closed. itb(OFdStreambuf(int fd, size_t n = 1)) This constructor initializes the streambuf, associating it to file descriptor tt(fd), and an optional unget buffer size (by default having size 1). When the object is destroyed or if the mode-less overloaded version of the bf(open) member is called, the file descriptor will be closed. itb(OFdStreambuf(int fd, Mode mode, size_t n = 1)) This constructor initializes the streambuf, associating it to file descriptor tt(fd), and an optional unget buffer size (by default having size 1). When the object is destroyed or if the mode-less overloaded version of the bf(open) member is called, the bf(Mode) argument determines whether the file descriptor will be closed or will remain open. ) There are no copy or move constructors. manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(FBB::OFdStreambuf) inherits from this class. Some of the bf(std::streambuf)'s member are overridden by bf(FBB::OFdStreambuf), see below. itemization( itb(void close()) The file descriptor used by the tt(OFdStreambuf) is closed, irrespective of the tt(Mode) that was specified when the tt(OFdStreambuf) object was constructed. Following tt(close) the tt(OFdStreambuf) object can no longer be used until one of its tt(open) members has been called. itb(int fd() const) The file descriptor used by the tt(OFdStreambuf) object is returned. If the tt(OFdStreambuf) is not associated with a file descriptor -1 is returned. itb(void open(int xfd, size_t n = 1)) The streambuf is (re)initialized, using file descriptor tt(fd), and an optional unget buffer size (by default having size 1). When called repeatedly, the bf(Mode) specification used whem the object was constructed determines whether the file descriptor will be closed or will remain open. itb(void open(int xfd, Mode mode, size_t n = 1)) The streambuf is (re)initialized, using file descriptor tt(fd), a file descriptor closing parameter and an optional unget buffer size (by default having size 1). Depending on the bf(Mode) argument the object's currently used file descriptor will be closed or will remain open when the tt(IFdStreambuf) object is destroyed. ) The overloaded assignment operator is not available. manpagesection(PROTECTED MEMBER FUNCTION) The member listed in this section implements the tasks of the comparably named virtual function in the class's private interface. This separates the redefinable interface from the user-interface. The class bf(OFdStreambuf) can, in accordance with Liskov's Substitution Principle, be used as a tt(std:streambuf); but it also offers a facility for classes deriving from bf(OFdStreambuf). This facility is listed here. itemization( itb(int pSync()) The contents of the bf(OFdStreambuf)'s internal buffer are flushed. If writing the contents to the file descriptor fails, a warning message is displayed to the standard error stream. ) manpagesection(EXAMPLE) To do manpagefiles() em(bobcat/ofdstreambuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ifdstreambuf)(3bobcat), bf(ofdstream)(3bobcat), bf(std::streambuf) manpagebugs() None reported includefile(include/trailer) bobcat-3.19.01/documentation/man/indent.yo0000644000175000017500000000626512222576536017404 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Indent)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Text Indentation) manpagename(FBB::Indent)(Configurable text indentation) manpagesynopsis() bf(#include )nl() manpagedescription() bf(FBB::Indent) and its various manipulators offer text-indentation. Text inserted into streams is indented over a fully configurable amount using a set of manipulators and (static) member functions. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(STATIC MEMBER FUNCTIONS) itemization( itb(void clear()) Resets the indentation level to zero. The bf(indent) manipulator will have no visible effect after calling this member. itb(void dec()) Reduces the indentation level by the current increment (4 by default). The indentation level is never reduces to a negative value. itb(void inc()) Increments the indentation level by the current increment (4 by default). itb(void setInc(size_t inc)) Defines the increment value used with the bf(dec) and bf(inc) members. itb(void setWidth(size_t width)) Defines the indentation to a specific value bf(width). ) manpagesection(MANIPULATORS) The following manipulators (which are em(not) part of the bf(FBB::Indent), class, but em(are) defined in the bf(FBB) namespace) can be inserted into the bf(FBB::Indent) object: itemization( itb(FBB::decindent) This manipulator will first call bf(Indent::dec). Then bf(FBB::indent) is called. The effect will be that the indentation level is reduced just before the indentation is inserted. itb(FBB::incindent) This manipulator will first call bf(Indent::inc). Then bf(FBB::indent) is called. The effect will be that the indentation level is incremented just before the indentation is inserted. itb(FBB::indent) This manipulator will insert the currently defined number of indentation blanks into the tt(ostream) for which it it called. itb(FBB::indentdec) This manipulator will first call bf(FBB::indent), Then bf(Indent::dec) is called. The effect will be that the indentation is inserted first, immediately followed by a reduction of the indentation level. itb(FBB::indentinc) This manipulator will first call bf(FBB::indent), Then bf(Indent::inc) is called. The effect will be that the indentation is inserted first, immediately followed by a increment of the indentation level. itb(FBB::nlindent) This manipulator will insert a newline character (tt(\n)). Then bf(FBB::indent) is called, indenting the next line over the currently defined number of blanks. ) manpagesection(EXAMPLE) verb( using namespace std; using namespace FBB; int main() { cout << indentinc << "Not indented" << nlindent << "Indenting with 4 blanks\n"; Indent::clear(); cout << "No indentation\n"; } ) manpagefiles() em(bobcat/indent) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/gs.inc0000644000175000017500000000104012222576536016640 0ustar frankfrank itemization( it() bf(BLOCK_DEVICE): the object represents a block device it() bf(CHARACTER_DEVICE): the object represents a character device it() bf(DIRECTORY): the object represents a directory it() bf(FIFO): the object represents a named pipe (a queue) it() bf(REGULAR_FILE): the object represents a regular file it() bf(SOCKET): the object represents a socket it() bf(SYMBOLIC_LINK): the object represents a symbolic link it() bf(ANY): any of the above types ) bobcat-3.19.01/documentation/man/isharedstream.yo0000644000175000017500000001471712242407535020751 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::ISharedStream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (std::istream on shared memory) manpagename(FBB::ISharedStream)(std::istream operations on shared memory) manpagesynopsis() bf(#include )nl() Linking option: tt(-lpthread -lbobcat) manpagedescription() This class offers the features of the bf(std::istream) class, operating on shared memory. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::ISharedStreambuf) (private inheritance),nl() bf(std::istream),nl() bf(FBB::SharedEnum__) (cf. bf(sharedmemory(3bobcat)) for a description of this last base class). manpagesection(CONSTRUCTORS) itemization( itb(ISharedStream()) The default constructor defines a stub a bf(ISharedStream) object that cannot immediately be used to access shared memory. To use it, its member tt(open) must first be called. itb(ISharedStream(size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::in, size_t access = 0600)) This constructor creates an tt(std::istream) that interfaces to a shared memory segment having a capacity of at least tt(maxSize * sizeUnit) bytes. By default, the shared memory segment is opened for reading. Different from the open modes used for file streams, creating a shared memory stream with open modes tt(ios::in) is OK. In this case the shared memory segment is created and once information has been written to the shared memory by another process (or object) the information can be read. The shared memory's access rights are defined by the tt(access) parameter, using the well-known (bf(chmod)(1)) way to define the access rights for the owner, the group and others, using octal digits. If construction succeeds the shared memory is ready for use. If construction fails, an tt(FBB::Exception) is thrown. itb(ISharedStream(int id, std::ios::openmode openMode = std::ios::in)) This constructor creates an tt(std::istream) that connects to a shared memory segment having ID tt(id). If construction succeeds the shared memory is ready for use. If construction fails (e.g., no shared memory segment having ID tt(id) exists), an tt(FBB::Exception) is thrown. ) Copy and move constructors are not available. manpagesection(OVERLOADED OPERATORS) The overloaded move and copy assignment operators are not available. manpagesection(MEMBER FUNCTIONS) All members of tt(std::istream) and tt(std::ostream) and the tt(enum) values tt(kB, MB), and tt(GB), defined by tt(FBB::ISharedEnum__) are available. itemization( itb(void clear()) This member clears the error states of the tt(std::istream) base class object. itb(int id() const) The ID of the shared memory segment is returned. itb(void kill()) Without locking the shared memory first, all shared memory is returned to the operating system. The bf(FBB::ISharedStream) object is unusable after returning from tt(kill). Other processes that were using the shared memory can continue to do so. itb(void remove()) The shared memory is first locked. Next, all shared memory is returned to the operating system. The bf(FBB::ISharedStream) object is unusable after returning from tt(remove). Other processes that were using the shared memory can continue to do so. itb(void memInfo(std::ostream &out, char const *end = "\n")) Information about the tt(ISharedMemory) object is inserted into the provide tt(ostream) object. The IDs of the shared segments, their sizes, the maximum number of shared memory segments, the number of bytes that can be read from the shared memory, and its actual storage capacity, etc., are displayed. Following the information about the shaed memory, tt(end) is inserted into tt(out). itb(void open(size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::in, size_t access = 0600)) This member creates a shared memory segment having a capacity of at least tt(maxSize * sizeUnit) bytes, and connects the shared memory segment to the bf(FBB::ISharedStream). A matching tt(close) member does not exist and is not required. By default, the shared memory segment is opened for reading. Different from the open modes used for file streams, creating a shared memory stream with open modes tt(ios::in) is OK. In this case the shared memory segment is created and once information has been written to the shared memory by another process it can be read. The shared memory's access rights are defined by the tt(access) parameter, using the well-known (bf(chmod)(1)) way to define the access rights for the owner, the group and others, using octal digits. If opening succeeds the shared memory is ready for use. If opening fails, an tt(FBB::Exception) is thrown. itb(void open(int id, std::ios::openmode openMode = std::ios::in)) This member connects the bf(FBB::ISharedStream) object to a shared memory segment having ID tt(id). A matching tt(close) member does not exist and is not required. If opening succeeds the shared memory is ready for use. If opening fails (e.g., no shared memory segment having ID tt(id) exists), an tt(FBB::Exception) is thrown. ) manpagesection(EXAMPLE) See the bf(sharedstream)(3bobcat) man page. manpagefiles() em(bobcat/isharedstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(chmod)(1), bf(osharedstream)(3bobcat), bf(sharedblock)(3bobcat), bf(sharedmemory)(3bobcat), bf(sharedmutex)(3bobcat), bf(sharedpos)(3bobcat), bf(sharedsegment)(3bobcat), bf(sharedstream)(3bobcat), bf(sharedstreambuf)(3bobcat) manpagebugs() Note that by default exceptions thrown from within a bf(std::stream) object are caught by the stream object, setting its tt(ios::failbit) flag. To allow exceptions to leave a stream object, its tt(exceptions) member can be called, e.g., using: verb( myStream.exceptions(ios::failbit | ios::badbit | ios::eofbit); ) includefile(include/trailer) bobcat-3.19.01/documentation/man/sharedmemory.yo0000644000175000017500000002422312242120566020602 0ustar frankfrankincludefile(include/header) COMMENT(replace 'sharedmemory' by the name of the new class) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::SharedMemory)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Shared Memory Memory) manpagename(FBB::SharedMemory)(Shared Memory memory structure) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat ) manpagedescription() The class bf(FBB::SharedMemory) implements a usable interface to a shared memory segment made available by tt(FBB::SharedSegment) and monitored by tt(FBB::SharedPos). It is the main building block for tt(FBB::SharedStreambuf), defining the `device' to which tt(FBB::SharedStreambuf) interfaces. All shared memory related I/O should be performed through an bf(FBB::SharedMemory) object, which is a true object, not itself residing in shared memory. An bf(FBB::SharedMemory) object defines, connects to and manages access to shared memory, encapsulating all raw shared memory operations. In addition to the class bf(FBB::SharedMemory) the header file tt(bobcat/sharedmemory) also defines a bf(struct SharedEnum__) defining an bf(enum SizeUnit). The total amount of requested shared memory is always a lower bound to the actual amount of shared memory that eventually may become available. As a fictitious example: assume 100 kB of memory is requested, then a table of, e.g., 10 entries is maintained, each entry controlling the access to a shared memory block of, 10 kB. These 10 kB blocks aren't immediately allocated, but become available once the program reads from or writes to addresses located in these data blocks. Whenever a data block is created it is initialized to 0-bytes. Caveat: when constructing a shared memory segment make sure the segment's ID is stored at a retrievable location. This allows other processes to access the shared segment. The shared segment ID is also required to delete a shared memory segment. If the shared segment ID is lost, the memory occupied by the shared memory segment remains inaccessible, and will reduce the amount of usable memory until the computer is rebooted. The member function tt(id) returns the ID of the shared memory currently monitored by an bf(FBB::SharedMemory) object. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::SharedEnum__) The bf(struct SharedEnum__) is a wrapper struct around bf(enum SizeUnit), which is available through inheritance in several bf(FBB::Shared*) classes, and offers symbolic constants defining standard memory sizes. The bf(enum SizeUnit) defines the following symbolic constants: itemization( itb(kB), representing 2+sups(10) bytes of memory; itb(MB), representing 2+sups(20) bytes of memory; itb(GB), representing 2+sups(30) bytes of memory ) manpagesection(CONSTRUCTORS, DESTRUCTOR) itemization( itb(SharedMemory()) The default constructor does not yet access a shared memory segment, but can be used to define a stub bf(FBB::SharedMemory) object, to be used at some later point during the execution of a program. itb(SharedMemory(size_t maxSize, SizeUnit sizeUnit, size_t access = 0600)) This constructor creates a shared memory segment having a capacity of at least tt(maxSize * sizeUnit) bytes. The shared memory's access rights are defined by the tt(access) parameter, using the well-known (bf(chmod)(1)) way to define the access rights for the owner, the group and others. If construction succeeds the shared memory is ready for use. If construction fails, an tt(FBB::Exception) is thrown. itb(SharedMemory(int id)) This constructor connects to a shared memory segment having ID tt(id). If construction succeeds the shared memory is ready for use. If construction fails (e.g., no shared memory segment having ID tt(id) exists), an tt(FBB::Exception) is thrown. itb(~SharedMemory()) The destructor detaches any attached shared memory segments from the bf(FBB::SharedMemory) object. If the shared memory segment is currently locked by the bf(FBB::SharedMemory) object, the lock is removed. ) copy and move constructors are not available. manpagesection(OVERLOADED OPERATORS) itemization( itb(std::ostream &operator<<(std::ostream &out, SharedMemory const &sharedMemory)) The overloaded insertion operator inserts information about the tt(SharedMemory) object into the provide tt(ostream) object. The IDs of the shared segments, their sizes, the maximum number of shared memory segments, the number of bytes that can be read from the shared memory, and its actual storage capacity, etc., are displayed. itb(SharedMemory &operator=(SharedMemory &&rhs)) The overloaded move assignment operator is available. It is used to (re)define the shared memory segment an bf(FBB::SharedMemory) object is interfacing with. ) The overloaded copy assignement operator is not available. manpagesection(MEMBER FUNCTIONS) itemization( itb(void clear()) First, the shared memory is locked. Next, all shared data segment are deleted, and the shared memory's own data are reset to indicate it is completely empty. Following this the shared memory segment is unlocked again. Returning from tt(clear) the shared memory The bf(FBB::SharedMemory) object is effectively re-initialized, with tt(offset) and tt(nReadable) returning 0. itb(int get()) First the bf(FBB::SharedMemory) object calls tt(lock) to lock the shared memory segment. Next the character at tt(offset) is retrieved and tt(offset) is incremented. Then tt(unlock) is called, and the retrieved character is returned. If tt(offset) is at least equal to tt(nReadable, EOF) is immediately returned. itb(int id() const) The ID of the shared memory segment is returned. itb(void kill()) Without locking the shared memory all shared memory controlled by the bf(FBB::SharedMemory) object is deleted. The bf(FBB::SharedMemory) object is unusable after returning from tt(kill). itb(std::streamsize maxOffset() const) The maximum possible offset that can be used with the shared memory segment is returned. The members tt(offset) and tt(nReadable) never exceed the value returned by tt(maxOffset). itb(std::streamsize nReadable() const) The number of characters (bytes) that can be read from the beginning of the shared memory is returned. itb(std::streamsize offset() const) The offset within the shared memory segment is returned. itb(char *ptr()) Returns 0 if tt(offset() == maxOffset()). Otherwise it returns a pointer to the character at index tt(offset) within the shared memory segment. itb(int put(int ch)) After locking the appropriate shared data segment, tt(ch) is written at position tt(offset), incrementing tt(offset) thereafter. If tt(ch == EOF, EOF) is immediately returned. itb(int read(char *data, std::streamsize len)) While locking the appropriate shared data segment(s) at most tt(len) bytes are read from the shared memory, starting at tt(offset). The bytes read from shared memory are stored at tt(data). The number of bytes actually written is returned. This member returns -1 if initially tt(offset) was at least equal to tt(nReadable). itb(void remove()) The shared memory is locked, after which all shared memory controlled by the bf(FBB::SharedMemory) object is deleted. The bf(FBB::SharedMemory) object is unusable after returning from tt(remove). itb(std::ios::pos_type seek(std::ios::off_type offset, std::ios::seekdir way = std::ios::beg)) Moves the tt(offset) position relative to tt(way). The value -1 is returned when seeking before offset 0 or beyond tt(maxOffset). itb(std::streamsize showmanyc() const) The number of characters that can be read from the current shared segment data block is returned. This member interrogates the number of readable characters in the shared memory segment. This number may change while this member is being executed. In order to receive a stable return value, calling functions should have obtained a lock on the shared memory segment before calling this member. itb(void swap(SharedMemory &other)) The current and other bf(FBB::SharedMemory) objects are swapped. itb(bool try_lock() const) When returning tt(true) the current process has obtained the lock, and the object's lock count is set to 1. Otherwise, tt(false) is returned (which includes the case where the process already has obtained the lock). itb(void unlock() const) If the object's lock count is zero, the function immediately returns. Otherwise, the object's lock count is decremented. Once the lock count has decremented to zero the lock of the shared memory segment is released. itb(int write(char const *data, std::streamsize len)) The bf(FBB::SharedMemory) object calls tt(lock) to lock the shared memory, and writes at most tt(len) bytes into the shared memory, starting at tt(offset). Next, tt(unlock) is called. The number of bytes actually written is returned. The member function returns -1 if initially tt(offset) is equal to tt(maxOffset). ) manpagesection(EXAMPLE) See the bf(sharedstream)(3bobcat) man page. manpagefiles() em(bobcat/sharedmemory) - defines the class interface manpageseealso() bf(bobcat)(7), bf(chmod)(1), bf(isharedstream)(3bobcat), bf(osharedstream)(3bobcat), bf(sharedblock)(3bobcat), bf(sharedmutex)(3bobcat), bf(sharedpos)(3bobcat), bf(sharedsegment)(3bobcat), bf(sharedstream)(3bobcat), bf(sharedstreambuf)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/ifilterstreambuf.yo0000644000175000017500000001415612222576536021470 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::IFilterStreambuf)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz)(Filtering Input Stream Buffer) manpagename(FBB::IFilterStreambuf) (Filtering stream buffer initialized by a std::istream object) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::IFilterStreambuf) objects may be used as a bf(std::streambuf) for tt(std::istream) objects, filtering the information produced by those objects. The class tt(IFilterStreambuf) was designed with the bf(openSSL BIO) (cf. bf(bio)(3ssl)) in mind. Since the BIO concept was developed in the context of the bf(C) programming language, BIOs do not support bf(C++) streams. Nonetheless, the concept of a filtering device is an attractive one, and is offered by the bf(FBB::IFilterStreambuf) class. In addition to filtering, bf(IFilterStreambuf) objects use split buffers, and thus, depending on the (configurable) size of buffer that is maintained by bf(IFilterStreambuf) objects, usually multiple characters read from the bf(IFilterStreambuf) can be pushed back again. The class bf(IFilterStreambuf) is an abstract base class. It is used via classes that are derived from bf(IFilterStreambuf), implementing its pure virtual tt(load) member (see below at bf(PRIVATE VIRTUAL MEMBER FUNCTIONS)). includefile(include/namespace) manpagesection(INHERITS FROM) bf(std::streambuf) manpagesection(MEMBER FUNCTIONS) All members of bf(std::streambuf) are available, as bf(IFilterStreambuf) inherits from this class. Some of the bf(std::streambuf)'s member are overridden by bf(IFilterStreambuf), see the next section. Overloaded move and/or copy assignment operators are not available. manpagesection(PROTECTED CONSTRUCTOR) itemization( itb(IFilterStreambuf(size_t bufSize = 1000)) This constructor initializes the streambuf, using a buffer of the indicated size. While the streambuf is being used, its buffer is gradually filled. Eventually, when it is full the oldest characters are removed from the buffer, making room for more recent characters. At most half the tt(bufSize) number of characters will be removed during a single refill. The constructor ensures that the size of the buffer will always be at least 100. ) Copy- and move constructors are not available. manpagesection(PROTECTED MEMBER FUNCTION) itemization( itb(void setBuffer()) This member initializes the base class's buffer pointers (i.e., tt(eback, gptr,) and tt(egptr)) with the initial range of characters retrieved by tt(filter) (see below). The member tt(setBuffer) should only once be called from the derived class's constructor. Once it has been called, the tt(peek) member of the tt(std::istream) that is initialized with the bf(IFilterStreambuf) will return the next available character, even if no other stream operation has as yet been performed. If it is not called by the derived class's constructor, then tt(peek) returns 0 until at least one character has been retrieved from the tt(istream) object. ) manpagesection(PRIVATE VIRTUAL MEMBER FUNCTIONS) itemization( itb(virtual bool filter(char const **srcBegin, char const **srcEnd) = 0) The tt(filter) member is declared as a pure virtual member: derived classes em(must) override tt(filter) with their own implementation. Derived class objects are responsible for obtaining information (in any amount) from the device with which they interact. This information is then passed on to the tt(IFilterStreambuf) via two pointers, pointing, respectively, to the first available character and beyond the last available character. The characters indicated by this range are subsequently transferred by the bf(IFilterStreambuf) object to its own buffer, from where they are then retrieved (or to where they can be pushed back) by the application. The tt(filter) member allows implementations to filter and/or modify the information that is obtained by this member. The bf(EXAMPLE) section below provides an example filtering out a configurable set of characters from a provided tt(std::istream). Bobcat's classes bf(ISymCryptStreambuf)(3bobcat) and bf(IBase64Streambuf)(3bobcat) provide additional examples of classes derived from bf(IFilterStreambuf). The tt(filter) member should return tt(false) if no (more) information is available. It should return tt(true) if information is available, in which case tt(*srcBegin) and tt(*srcEnd) should be pointing to, respectively, the first character and beyond the last character made available by tt(filter); itb(int pbackfail() final override) The tt(pbackfail) member is final; derived classes cannot override it. Currently it merely returns tt(EOF). This may change in future implementations. itb(std::streamsize showmanyc() final override) The tt(showmanyc) member is final; derived classes cannot override it. It returns the current number of characters that are (still) waiting to be processed in the range of characters returned by the latest tt(filter) call. itb(int underflow() final override) The tt(underflow) member is final; derived classes cannot override it. It calls tt(filter), and refreshes at most half the size of its internal buffer with characters from the range of characters that was returned by the most recent call of tt(filter). ) The tt(final) attribute was added to the above three members to give tt(IFilterStreambuf) objects full control over their own buffers. manpagesection(EXAMPLE) Here is a class, derived from tt(IFilterStreambuf), filtering out a predefined set of characters. It is used twice to filter digits and vowels, to illustrate chaining of bf(IFilterStreambuf) objects. verbinclude(../../ifilterstreambuf/driver/driver.cc) manpagefiles() em(bobcat/ifdstreambuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(isymcryptstreambuf)(3bobcat), bf(ibase64streambuf)(3bobcat), bf(ofilterstreambuf)(3bobcat). bf(std::streambuf) manpagebugs() None reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/stringline.yo0000644000175000017500000000457012222576536020276 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::StringLine)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Line extractor) manpagename(FBB::StringLine)(extracting lines using operator>>) manpagesynopsis() bf(#include )nl() manpagedescription() The standard tt(operator>>(std::istream &, std::string &)) string extracion operator extracts the first `word' from a stream. In cases where the intent it to extract lines from the stream this operator cannot be used, but tt(getline(std::istream &, std::string &)) is usually called. However, tt(getline) is not called by many tools of generic algorithms, like the tt(istream_iterator). The class (actually: struct) tt(StringLine) was simply derived from tt(std::string), and defines its own tt(operator>>), reading the next line from the specified tt(std::istream). includefile(include/namespace) manpagesection(INHERITS FROM) tt(std::string) manpagesection(CONSTRUCTORS) tt(StringLine) is an empty shell around tt(std::string). It does not explicitly define constructors. The default and copy constructors are available. manpagesection(OVERLOADED OPERATOR) itemization( itb(std::istream &operator>>(std::istream &in, StringLine &str)) The extraction operator returns the next line on tt(in) in tt(str), calling tt(getline(std::istream &, std::string &)). ) manpagesection(MEMBER FUNCTIONS) All members of bf(std::string) are available, as bf(FBB::StringLine) inherits from these classes. manpagesection(EXAMPLE) The following example extracts all lines from tt(std::cin) and adds them to the tt(std::vector lines): verb( #include #include #include #include #include using namespace std; using namespace FBB; int main() { vector lines; copy( istream_iterator(cin), istream_iterator(), back_inserter(lines) ); } ) manpagefiles() em(bobcat/stringline) - defines the class interface and tt(operator>>). There are tt(StringLine) object files in the Bobcat library, so linking to Bobcat when using tt(StringLine) is not necessary. manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/stat.yo0000644000175000017500000002356412222576536017077 0ustar frankfrankincludefile(include/header) COMMENT( see also getgroups ) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Stat)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Characteristics of object in the filesystem) manpagename(FBB::Stat)(Determines File Characteristics) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(Stat) is a wrapper around the bf(stat)(2) system function. In particular, it offers features to test directly for object characteristics offered by bf(stat)(2). To determine whether an object exists the tt(Stat bool) conversion operator can be used. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ENUMERATIONS) bf(Stat::Combine): nl() This enumeration defines the following values: itemization( it() bf(ALL): require all of the specified bf(Mode) or bf(SpecialMode) values to match; it() bf(ANY): require any match of the specified bf(Mode) or bf(SpecialMode) values (one match suffices); ) bf(Stat::Mode): nl() This enumeration defines the following values: itemization( it() bf(UR): the owner of the object has read permissions it() bf(UW): the owner of the object has write permissions it() bf(UX): the owner of the object has execute permissions it() bf(GR): the group to which the object belongs has read permissions it() bf(GW): the group to which the object belongs has write permissions it() bf(GX): the group to which the object belongs has execute permissions it() bf(OR): others have read permissions it() bf(OW): others have write permissions it() bf(OX): others have execute permissions it() bf(READ): equal to tt(UR | GR | OR) it() bf(WRITE): equal to tt(UW | GW | OW) it() bf(EXEC): equal to tt(UX | GX | OX) it() bf(RWX): all of the above. ) bf(Stat::SpecialMode): nl() This enumeration defines the following values: itemization( it() bf(SUID): set UID bit is up it() bf(SGID): set GID bit is up it() bf(SB): sticky bit is up ) bf(Stat::Type): nl() This enumeration, which is identical to the bf(glob)(3bobcat) tt(Type) enumeration), defines the following values: includefile(gs.inc) manpagesection(CONSTRUCTORS) itemization( itb(Stat()) The default constructor, creating an empty bf(Stat) object. itb(Stat(std::string const &fname)) Initializes a bf(Stat) with a given object name. itb(Stat(std::string const &fname, std::string const &searchPath)) Initializes a bf(Stat) with a given object name, where the object is searched in the tt(searchPath) directories, which is a colon-separated string of directory names. The filenames are constructed by appending tt(fname) to each of the elements of tt(searchPath) until an existing object is found. This object is then used. If tt(fname) is an absolute path, tt(searchPath) is ignored. ) The copy constructor is available. manpagesection(OVERLOADED OPERATORS) itemization( itb(operator bool() const) This operator returns tt(true) if the tt(Stat) object holds information about an existing object. Otherwise tt(false) is returned. ) The default assignment operator is available. manpagesection(MEMBER FUNCTIONS) itemization( itb(bool access(FBB::User const &user, size_t spec, bool useEffective = true) const) Returns tt(true) if tt(user) has the permissions as specified at tt(spec) (of which only the defined tt(Mode) bits are interpreted). If a combination of read, write and/or execute permissions are specified, then at least one of the read permissions, one of the write permissions and one of the execute permissions must be granted or the function returns tt(false). E.g, when specifying tt(access(user, UW | UR | GR)) then the user em(must) have write permissions, but either the user or the user's group must have read permissions. If multiple read, multiple write or multiple execute permissions are specified (like tt(UR | GR)) then this member returns tt(true) if at least one of the requested read, write, or execute permissions are granted for tt(user). itb(size_t blockSize() const) Returns the blocksize (tt(st_blksize)) for filesystem I/O itb(size_t device() const) Returns the device id (tt(st_dev)). itb(size_t deviceType() const) Returns the device type number, but only if the object type is bf(DEVICE) (tt(st_rdev)). itb(size_t error() const) Returns the error number associated with an error, in cases where bf(operator bool()) returns bf(false). A returned value of 0 indicates `no errors'. itb(bool isType(Stat::Type probe)) Returns tt(true) if the object has the probed type otherwise tt(false) is returned. itb(size_t inode() const) Returns the inode number (tt(st_ino)). itb(size_t gid() const) Returns the group ID of the object's owner (tt(st_gid)). itb(FBB::DateTime lastAccess() const) Returns a bf(FBB::DateTime) object holding information about the object's time of last access (tt(st_atime)) (using UTC). itb(FBB::DateTime lastChange() const) Returns a bf(FBB::DateTime) object holding information about the object's time of last status change (tt(st_ctime)) (using UTC). itb(FBB::DateTime lastModification() const) Returns a bf(FBB::DateTime) object holding information about the object's last modification time (tt(st_mtime)) (using UTC). itb(size_t mode() const) Returns the object's raw, uninterpreted mode (tt(st_mode & RWX)). Note that this value is usually displayed (and is processed most easily) as an octal value. itb(bool mode(size_t mode, Combine combine = ALL)) Returns true if the object has the indicated mode. Multiple modes may be set, which can be combined by the logical bf(bitor) operator. By default, if multiple modes are specified, the resulting pattern must exactly represent the object's mode for the member function to return bf(true). An optional argument tt(ANY) may be specified if the function should return true if at least one specified mode matches the object's actual mode. An tt(Exception) exception is thrown if the specified tt(mode) contains other values than the defined bf(Mode) or bf(SpecialMode) values. itb(std::string modeStr() const) Returns the standard string-representation of the object's mode (e.g., tt(rw-r--r--)). Special modes (e.g., suid) are indicated by tt(s) instead of tt(x) when the object is user and/or group executable and by tt(S) if the object has the special mode bit(s) set, but is not executable. For the `other' executable mode flag tt(t) is used (`sticky' bit) and tt(T) if the object is not `other' executable. itb(std::string const &name() const) Returns the object's name as specified in the constructor or bf(set()) member function. itb(size_t nBlocks() const) Returns the object's number of allocated blocks (tt(st_blocks)). itb(size_t nLinks() const) Returns the object's number of hard links (tt(st_nlink)). itb(std::string path() const) Returns the object's full pathname. If the full pathname could not be determined, an empty string is returned. itb(bool set(std::string const &name)) Redefine the bf(Stat) object to represent the information about the indicated object name. itb(bool set(std::string const &name, std::string const &pathlist)) Redefine the bf(Stat) object to represent the information about the indicated object name, where the object is searched in the tt(pathlist) directories, which is a colon-separated string of directory names. The object names are constructed by appending tt(fname) to each of the elements of tt(searchPath) until an existing object is found. This object is then used. If tt(fname) is an absolute path, tt(searchPath) is ignored. itb(off_t size() const) Returns the object's size in number of bytes (tt(st_size)). itb(bool specialMode(size_t special, Combine combine = ALL)) Returns true if the object has the indicated special modes. Multiple special modes may be specified, which can be combined by the logical bf(bitor) operator. By default, if multiple modes are specified, the resulting pattern must exactly represent the object's mode for the member function to return bf(true). An optional argument tt(ANY) may be specified if the function should return true if at least one specified mode matches the object's actual mode. The non-special modes are ignored but a tt(Exception) exception is thrown if tt(special) contains other values than those defined by the bf(SpecialMode) enum. itb(Stat::stat const &statStruct() const) Returns a reference to the object's bf(stat struct). itb(Stat::Type type() const) Returns the tt(Stat::Type) value of the object. itb(std::string typeStr() const) Returns a textual representation of the object's type as returned by the tt(Stat::type()) member function. itb(size_t uid() const) Returns the user ID of the object's owner (tt(st_uid)). ) manpagesection(EXAMPLE) verbinclude(../../stat/driver/driver.cc) manpagefiles() em(bobcat/stat) - defines the class interface manpageseealso() bf(bobcat)(7), bf(glob)(3bobcat), bf(stat)(3) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/sharedsegment.yo0000644000175000017500000001727212242122535020740 0ustar frankfrankincludefile(include/header) COMMENT(replace 'sharedsegment' by the name of the new class) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::SharedSegment)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Shared Memory Data) manpagename(FBB::SharedSegment)(Shared Memory data structure) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat ) manpagedescription() The class bf(FBB::SharedSegment) implements the shared memory data structure which is used by Bobcat's shared memory classes. Bobcat's tt(SharedMemory) class accesses or defines a shared memory segment which is interpreted as an tt(FBB::SharedSegment) object. The total amount of requested shared memory is always a lower bound to the actual amount of shared memory that eventually may become available. As a fictitious example: assume 100 kB of memory is requested, then the bf(FBB::SharedSegment) object, maintains a table of, e.g., 10 entries, each controlling the access to a shared memory block of 10 kB. These 10 kB blocks aren't immediately allocated, but become available once the program reads from or writes to addresses located in these data segments. The class bf(FBB::SharedSegment) therefore defines a gateway, controlling access to and allocating the shared memory data segment. The mentioned table consists of tt(nBlocks SharedBlock) (bf(sharedblock)(3bobcat)) values, offering mutexes and IDs of shared data segments. As always, the mutexes control which process has access to a particular block of shared data memory, and the IDs are either -1, meaning that their shared memory data segments has as not yet been defined, or they contain the IDs of defined shared memory data segments. The class bf(FBB::SharedSegment)'s sole responsibility is to offer the framework as described. When used by a tt(FBB::SharedMemory) object different processes may gain access to different parts of the shared memory data without interfering each other's read and write actions. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) No publicly accessible constructors have been defined for bf(FBB::SharedSegment). A static member function tt(create) (see below) is available, returning a pointer to a shared memory segment, in which a bf(FBB::SharedSegment) has been defined. manpagesection(OVERLOADED OPERATORS) itemization( itb(std::ostream &operator<<(std::ostream &out, SharedSegment const &sharedData)) The overloaded insertion operator inserts basic statistics of the shared memory data into the tt(ostream) object. Information about the IDs of the shared segments, their sizes, the maximum number of shared data segments and the number of bytes that can be read from the shared memory are displayed. itb(FBB::SharedBlock &operator[](size_t idx)) Table element tt(idx) of the table of tt(FBB::SharedBlock) block IDs is returned. The behavior of the program is undefined if tt(idx) is or exceeds tt(nBlocks()). ) Overloaded move and copy assignment operators are not available. manpagesection(MEMBER FUNCTIONS) itemization( itb(size_t access() const) The access rights of the shared memory segment are returned as a number which is usually interpreted as an octal value, using the well-known (bf(chmod)(1)) way to define the access rights for the owner, the group and others. itb(void clear()) All the shared memory data blocks are unconditionally deleted and tt(nReadable) returns 0 (the shared memory data blocks are not locked prior to deleting them). itb(void lock(size_t idx) const) Access to shared data segment tt(idx) is locked. This member itself does not support recursive locking. itb(size_t nBlocks() const) The number of shared memory data blocks that can be used by the bf(FBB::SharedSegment) object is returned. itb(int newData(size_t idx)) The ID of a newly created shared memory data segment is returned. The ID is also stored in the table of shared memory data segments that is maintained by the bf(FBB::SharedSegment) object. itb(std::streamsize nReadable() const) The number of characters (bytes) that can be read from the beginning of the shared memory is returned. itb(void nReadableLock() const) When returning from this member function a lock has been obtained of bf(FBB::SharedSegment)'s mutex controlling access the the object's data member storing the number of characters that can be read from the shared memory controlled by the bf(FBB::SharedSegment) object. itb(void nReadableUnlock() const) This member function releases the lock previously acquired by tt(nReadableLock). itb(size_t segmentSize() const) The size (in bytes) of the shared memory data blocks is returned. The bf(FBB::SharedSegment) object can accomodate at most tt(segmentSize() * nBlocks()) bytes. itb(void unlock(size_t idx) const) Releases the lock on the shared memory data segment tt(idx). If the current process does not own the lock of shared memory data block tt(idx) nothing happens and the function immediately returns. itb(void updateNreadable(std::streamsize offset)) The number of bytes that can be retrieved from the shared memory is updated to tt(max(nReadable(), offset)). ) manpagesection(STATIC MEMBER FUNCTIONS) itemization( itb(void *attach(int id)) The address of shared memory segment tt(id), mapped to the calling process's memory area, is returned. itb(SharedSegment *create(int *id, size_t nBlocks, size_t segmentSize, size_t access)) This member returns a pointer to a new bf(FBB::SharedSegment) object, defined in the computer's shared memory, storing the shared memory's ID at tt(*id), and expecting the number of data blocks (tt(nBlocks)), the size of these data blocks (tt(segmentSize)), and the shared memory's access rights (tt(access), using the well-known (bf(chmod)(1)) way to define the access rights for the owner, the group and others) as its arguments. itb(void deleteSegment(int id)) The shared memory segment having ID tt(id) is deleted from memory. itb(Type *detach(Type *sharedPtr, bool requireOK = true)) This member is defined as a member template. It expects a pointer to a shared memory segment, previously mapped on the calling process's memory space by tt(attach), and detaches it from the process's memory space, returning 0. By default, detaching the memory must succeed or a bf(FBB::Exception) is thrown. Throwing an exception on failure can be prevented by passing tt(false) as the member's second argument. itb(size_t size(int id)) The size (in bytes) of shared memory data block having ID tt(id) is returned. An tt(FBB::Exception) is thrown if the size of segment tt(id) cannot be determined. ) manpagesection(EXAMPLE) See the bf(sharedstream)(3bobcat) man page. manpagefiles() em(bobcat/sharedsegment) - defines the class interface manpageseealso() bf(bobcat)(7), bf(chmod)(1), bf(isharedstream)(3bobcat), bf(osharedstream)(3bobcat), bf(sharedblock)(3bobcat), bf(sharedmemory)(3bobcat), bf(sharedmutex)(3bobcat), bf(sharedpos)(3bobcat), bf(sharedstream)(3bobcat), bf(sharedstreambuf)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/localclientsocket.yo0000644000175000017500000001166612222576536021626 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::LocalClientSocket)(3bobcat) (_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Unix Domain client Socket) manpagename(FBB::LocalClientSocket) (Client Socket connecting to a Server in the Unix Domain) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() An bf(FBB::LocalClientSocket) may be constructed to connect to a server process in the Unix Domain. The socket made available by the bf(FBB:LocalClientSocket) may be used to initialize a bf(std::istream) and/or bf(std::ostream). The bf(std::istream) is used to read information from the server process to which the bf(FBB::LocalClientSocket) connects, The bf(std::ostream) is used to send information to the server process to which the bf(FBB::LocalClientSocket) connects. Since a socket may be considered a em(file descriptor) the avaiable bf(FBB::IFdStream), bf(FBB::IFdStreamBuf), bf(FBB::OFdStream), and bf(FBB::OFdStreamBuf) classes may be used profitably here. Note that having available a socket does not mean that this defines the communication protocol. It is (still) the responsibility of the programmer to comply with an existing protocol or to implement a tailor-made protocol. The latter situation implies that the sequence of input- and output operations is defined by the programmer. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::LocalSocketBase) manpagesection(CONSTRUCTOR) itemization( itb(LocalClientSocket()) This constructor merely creates a bf(FBB::LocalClientSocket) object. Before it can be used, its tt(open()) member must be called. itb(LocalClientSocket(std::string const &name)) This constructor initializes an bf(FBB::LocalClientSocket) object, using the named Unix Domain socket to connect to the server using the named Unix Domain socket. An bf(FBB::Exception) is thrown if the socket could not be constructed. The construction of the socket does not mean that a connection has actually been established. In order to connect to the server, the member bf(connect()) (see below) should be used. ) The copy constructor is not available. manpagesection(MEMBER FUNCTION) itemization( itb(int connect()) This member returns a socket that can be used to communicate with the server process. An bf(FBB::Exception) exception is thrown if the connection could not be established. itb(open(std::string const &name)) This member function prepares the bf(FBB::LocalClientSocket) object, constructed earlier using the default constructor, for use. The named Unix Domain socket is used to connect to the server using the named Unix Domain socket. An bf(FBB::Exception) is thrown if the socket could not be constructed. The construction of the socket does not mean that a connection has actually been established. In order to connect to the server, the member bf(connect()) should be used. ) manpagesection(EXAMPLE) See also the bf(localserversocket)(3bobcat) example. verb( #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) { cerr << "Provide filename representing the unix domain socket\n"; return 1; } LocalClientSocket client(argv[1]); int fd = client.connect(); string line; cout << "Connecting to socket " << fd << endl; IFdStream in(fd); // stream to read from OFdStream out(fd); // stream to write to while (true) { // Ask for a textline, stop if empty / none cout << "? "; if (!getline(cin, line) || line.length() == 0) return 0; cout << "Line read: " << line << endl; // Return the line to the server out << line.c_str() << endl; cout << "wrote line\n"; // Wait for a reply from the server getline(in, line); cout << "Answer: " << line << endl; } return 0; } catch (Exception const &err) { cerr << err.what() << "\n" << "Can't connect to " << argv[1] << ", port " << argv[2] << endl; return 1; } ) manpagefiles() em(bobcat/localclientsocket) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ifdstream)(3bobcat), bf(ifdstreambuf)(3bobcat), bf(clientsocket)(3bobcat), bf(localserversocket)(3bobcat), bf(localsocketbase)(3bobcat), bf(ofdstream)(3bobcat), bf(ofdstream)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/sharedstream.yo0000644000175000017500000001605012242407532020565 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::SharedStream)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (I/O on shared memory) manpagename(FBB::SharedStream)(I/O operations on shared memory) manpagesynopsis() bf(#include )nl() Linking option: tt(-lpthread -lbobcat) manpagedescription() This class combines the features of the bf(std::istream) and bf(std::ostream) classes, operating on shared memory. As with tt(std::fstream) objects, a tt(seekp) or tt(seekg) member call is required to switch from writing to reading or v.v. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::SharedStreambuf) (private inheritance),nl() bf(std::istream),nl() bf(std::ostream),nl() bf(FBB::SharedEnum__) (cf. bf(sharedmemory)(3bobcat) for a description of this last base class). manpagesection(CONSTRUCTORS) itemization( itb(SharedStream()) The default constructor defines a stub a bf(SharedStream) object that cannot immediately be used to access shared memory. To use it, its member tt(open) must first be called. itb(SharedStream(size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::in | std::ios::out, size_t access = 0600)) This constructor creates a stream inheriting the facilities of an tt(std::istream) and tt(std::ostream) that interfaces to a shared memory segment having a capacity of at least tt(maxSize * sizeUnit) bytes. By default, the shared memory segment is opened for reading and writing. Different from the open modes used for file streams, creating a shared memory stream with open modes tt(ios::in | ios::out) is OK. In this case the shared memory segment is created and once information has been written to the shared memory it can also be read again. The shared memory's access rights are defined by the tt(access) parameter, using the well-known (bf(chmod)(1)) way to define the access rights for the owner, the group and others, using octal digits. If construction succeeds the shared memory is ready for use. If construction fails, an tt(FBB::Exception) is thrown. itb(SharedStream(int id, std::ios::openmode openMode = std::ios::in | std::ios::out)) This constructor creates a stream inheriting the facilities of an tt(std::istream) and tt(std::ostream) that connects to a shared memory segment having ID tt(id). If construction succeeds the shared memory is ready for use. If construction fails (e.g., no shared memory segment having ID tt(id) exists), an tt(FBB::Exception) is thrown. Specifying the tt(ios::trunc) flag immediately clears the contents of the shared memory. ) Copy and move constructors are not available. manpagesection(OVERLOADED OPERATORS) The overloaded move and copy assignment operators are not available. manpagesection(MEMBER FUNCTIONS) All members of tt(std::istream) and tt(std::ostream) and the tt(enum) values tt(kB, MB), and tt(GB), defined by tt(FBB::SharedEnum__) are available. itemization( itb(void clear()) This member clears the error states of the tt(std::istream) and tt(std::ostream) base class objects. itb(int id() const) The ID of the shared memory segment is returned. itb(void kill()) Without locking the shared memory first, all shared memory is returned to the operating system. The bf(FBB::SharedStream) object is unusable after returning from tt(kill). Other processes that were using the shared memory can continue to do so. itb(void remove()) The shared memory is first locked. Next, all shared memory is returned to the operating system. The bf(FBB::SharedStream) object is unusable after returning from tt(remove). Other processes that were using the shared memory can continue to do so. itb(void memInfo(std::ostream &out, char const *end = "\n")) Information about the tt(SharedMemory) object is inserted into the provide tt(ostream) object. The IDs of the shared segments, their sizes, the maximum number of shared memory segments, the number of bytes that can be read from the shared memory, and its actual storage capacity, etc., are displayed. Following the information about the shaed memory, tt(end) is inserted into tt(out). itb(void open(size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::in | std::ios::out, size_t access = 0600)) This member creates a shared memory segment having a capacity of at least tt(maxSize * sizeUnit) bytes, and connects the shared memory segment to the bf(FBB::SharedStream). A matching tt(close) member does not exist and is not required. By default, the shared memory segment is opened for reading and writing. Different from the open modes used for file streams, creating a shared memory stream with open modes tt(ios::in | ios::out) is OK. In this case the shared memory segment is created and once information has been written to the shared memory it can also be read again. The shared memory's access rights are defined by the tt(access) parameter, using the well-known (bf(chmod)(1)) way to define the access rights for the owner, the group and others, using octal digits. If opening succeeds the shared memory is ready for use. If opening fails, an tt(FBB::Exception) is thrown. itb(void open(int id, std::ios::openmode openMode = std::ios::in | std::ios::out)) This member connects the bf(FBB::SharedStream) object to a shared memory segment having ID tt(id). A matching tt(close) member does not exist and is not required. If opening succeeds the shared memory is ready for use. If opening fails (e.g., no shared memory segment having ID tt(id) exists), an tt(FBB::Exception) is thrown. Specifying the tt(ios::trunc) flag immediately clears the contents of the shared memory. ) manpagesection(EXAMPLE) verbinclude(../../sharedstream/driver/driver.cc) manpagefiles() em(bobcat/sharedstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(chmod)(1), bf(isharedstream)(3bobcat), bf(osharedstream)(3bobcat), bf(sharedblock)(3bobcat), bf(sharedmemory)(3bobcat) bf(sharedmutex)(3bobcat), bf(sharedpos)(3bobcat), bf(sharedsegment)(3bobcat), bf(sharedstreambuf)(3bobcat) manpagebugs() Note that by default exceptions thrown from within a bf(std::stream) object are caught by the stream object, setting its tt(ios::failbit) flag. To allow exceptions to leave a stream object, its tt(exceptions) member can be called, e.g., using: verb( myStream.exceptions(ios::failbit | ios::badbit | ios::eofbit); ) includefile(include/trailer) bobcat-3.19.01/documentation/man/isymcryptstreambuf.yo0000644000175000017500000001414212224222531022051 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::ISymCryptStreambuf)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz) (Symmetric Encryption Stream Buffer) manpagename(FBB::ISymCryptStreambuf) (Input Filtering stream buffer doing symmetric encryption) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat -lcrypto) manpagedescription() The information made available by bf(ISymCryptStreambuf) objects has been subject to symmetric encryption or decryption. The information to be encrypted or decrypted is made available to bf(ISymCryptStreambuf) object via tt(std::istream) objects. The tt(class ISymCryptStreambuf) is a class template, using a tt(FBB::CryptType) template non-type parameter. Objects of the class tt(FBB::ISymCryptStreambuf) encrypt the information they receive, objects of the class tt(FBB::ISymCryptStreambuf) decrypt the information they receive. See also section bf(ENUMERATION) below. All symmetric encryption methods defined by the OpenSSL library that can be selected by name may be used in combination with tt(EncryptBuf) objects. To select a particular encryption method an identifier is passed to the constructor. E.g., tt("aes-128-cbc") indicating the AES (Rijndael) method, using 128 bit sized keys and blocks using `cbc' mode (see below for an explanation). When providing shorter keys than expected by the method the provided key is extended by adding the required number of 0-bytes. (zero valued bytes, not tt('0') characters). Most modes use an em(initialization vector). The initialization vector must be provided at construction time. The matching decrypting object needs to know the initialization vector that was used when encrypting the data: the application must ensure that the matching decryption object receives the same initialization vector as the one that was provided to the encryption object. Initialization vectors are not security sensitive in the sense that they can be sent in the clear to the decryption object. What em(is) important, though, is that they contain random data when used `for real'. When an initialization vector is specified that is shorter than expected by the method it will be extended with the required number of 0-bytes. includefile(blockciphers) includefile(symcryptciphers) includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::IFilterStreambuf) manpagesection(MEMBER FUNCTIONS) All members of bf(FBB::IFilterStreambuf) are available, as bf(ISymCryptStreambuf) inherits from this class. Overloaded move and/or copy assignment operators are not available. manpagesection(ENUMERATION) bf(ISymCryptStreambuf) objects either encrypt or decrypt information. bf(ISymCryptStreambuf) objects of the class bf(FBB::ISymCryptStreambuf) encrypt the data they receive, bf(ISymCryptStreambuf) objects of the class bf(FBB::ISymCryptStreambuf) decrypt the data they receive. The values tt(ENCRYPT) and tt(DECRYPT) are defined in the tt(enum CryptType), which is defined in the tt(FBB) namespace. manpagesection(CONSTRUCTOR) itemization( itb(ISymCryptStreambuf( std::istream &in, char const *type, std::string const &key, std::string const &iv, size_t bufSize = 100, size_t filterBufSize = 1000, ENGINE *engine = 0)) This constructor initializes the streambuf. itemization( - tt(ISymCryptStreambuf) objects perform encryption;nl() tt(ISymCryptStreambuf) objects perform decryption;nl() - tt(ISymCryptStreambuf) objects obtain the bytes to encrypt or decrypt from tt(std::istream &in);nl() - The encryption method to use is specified by the tt(type) parameter. E.g., tt("bf-cbc") selects the Blowfish Cipher Block Chaining method;nl() - The symmetric key to use is specified by the tt(key) parameter;nl() - The initialization vector is specified by the tt(iv) parameter;nl() - The tt(FBB::ISymCryptStreambuf) internally used buffer will contain tt(bufSize) characters. The default value is the smallest value that is used. When a smaller tt(bufSize) value is specified, the default value is used;nl() - tt(FBB::ISymCryptStreambuf)'s tt(IFilterStreambuf) base class is initialized with a buffer of size tt(filterBufSize), using a lower bound of 100;nl() - The parameter tt(ENGINE) can be used to specify a hardware accelleration engine, as supported by the used encryption/decryption method. Its default argument value indicates that no hardware accelleration is available. ) ) Copy- and move constructors are not available. manpagesection(EXAMPLE) The example shows the construction of an tt(ISymCryptStreambuf) object tt(ebuf) which is used to initialize a tt(std::istream) object. The information read from this tt(istream) is encrypted using the Blowfish CBC method. A tt(ISymCryptStreambuf) object (tt(dbuf) reads the information from that stream and decrypts it again. The tt(std::istream din) object is initialized with the tt(ISymCryptStreambuf) object, and its contents is sent to tt(std::cout). The information that is presented at tt(std::cin) and that appears at tt(std::cout) should be identical. verbinclude(../../isymcryptstreambuf/driver/driver.cc) manpagefiles() em(bobcat/isymcryptstreambuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(encryptbuf)(3bobcat), bf(isymcryptstream)(3bobcat), bf(ibase64streambuf)(3bobcat), bf(ifilterstreambuf)(3bobcat), bf(ofilterstreambuf)(3bobcat), bf(std::streambuf). manpagebugs() Sep/Oct 2013: due to a change in library handling by the linker (cf. lurl(http://fedoraproject.org/wiki/UnderstandingDSOLinkChange) and lurl(https://wiki.debian.org/ToolChain/DSOLinking)) libraries that are indirectly required are no longer automatically linked to your program. With bf(BigInt) this is tt(libcrypto), which requires programs to link to both tt(bobcat) and tt(crypto). includefile(include/trailer) bobcat-3.19.01/documentation/man/sharedmutex.yo0000644000175000017500000000623512242113573020437 0ustar frankfrankincludefile(include/header) COMMENT(replace 'sharedmutex' by the name of the new class) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::SharedMutex)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Shared Memory Mutex) manpagename(FBB::SharedMutex)(Mutex for shared memory) manpagesynopsis() bf(#include )nl() Linking option: tt(-lpthread, -lbobcat ) manpagedescription() Shared memory may be used by multiple processes. To synchronize access to shared memory an bf(FBB::SharedMutex) may be defined inside a shared memory segment. An bf(FBB::SharedMutex) allows clients to lock a shared memory segment before reading or writing its contents. E.g., the Bobcat class tt(FBB::SharedSegment) defines a tt(SharedMutex) in its shared memory segment. The bf(FBB::SharedMutex) class uses the facilities offered by the tt(PThread) library to implement shared memory locking. To force unlocking a (possibly) locked shared memory segment, its destructor can be called. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(CONSTRUCTORS) itemization( itb(SharedMutex()) The default constructor initializes an bf(FBB::SharedMutex) object to a shared memory mutex (using the tt(PTHREAD_PROCESS_SHARED) attribute). As an bf(FBB::SharedMutex) object will normally be defined inside a shared memory segment the object's memory is already available. In this case placement new should be used to call the constructor. E.g., if a shared memory segment is attached to the current process at tt(d_shared), and an bf(FBB::SharedMutex) should be defined at tt(d_shared)'s address, then the bf(FBB::SharedMutex) object can be initialized like this: verb( new (d_shared) FBB::SharedMutex; ) ) The copy and move constructors are not available. The class's destructor releasea all of the current process's nested shared memory segment locks. To destroy an bf(FBB::SharedMuted) object that has been constructed using the placement tt(new) operator use verb( d_sharedMutex->~SharedMutex(); ) (assuming tt(SharedMutex *d_sharedMutex) points to the location where placement new has previously initialized the bf(FBB::SharedMutex) object.) manpagesection(MEMBER FUNCTIONS) itemization( itb(void lock() const) When returning from this member, the current process has locked the shared memory segment. itb(void unlock() const) The object's lock of the shared memory segment is released. ) manpagesection(EXAMPLE) See the bf(sharedstream)(3bobcat) man page. manpagefiles() em(bobcat/sharedmutex) - defines the class interface manpageseealso() bf(bobcat)(7) bf(isharedstream)(3bobcat), bf(osharedstream)(3bobcat), bf(sharedblock)(3bobcat), bf(sharedmemory)(3bobcat), bf(sharedpos)(3bobcat), bf(sharedsegment)(3bobcat), bf(sharedstream)(3bobcat), bf(sharedstreambuf)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/ohexstreambuf.yo0000644000175000017500000000774312222576536021001 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::OHexStreambuf)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz)(Write hex values) manpagename(FBB::OHexStreambuf)(Writes characters written to an ostream as hex values) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(OHexStreambuf) is a specialization of tt(FBB::OFilterStreambuf) inserting all the characters it receives to a destination file as 2-character wide hexadecimal values. Optionally a maximum linelength can be specified. Note that all information received by an tt(OHexStreambuf) object is inserted as (a series of) hexadecimal values, not only plain characters. E.g., when inserting the value 123 the characters tt('1', '2') and tt('3') are successively inserted and so this will result in the string tt(313233) being inserted into the destination stream. includefile(include/namespace) manpagesection(INHERITS FROM) FBB::OFilterStreambuf manpagesection(CONSTRUCTOR) itemization( itb(OFoldStreambuf(std::ostream &stream, size_t width = 0)) The hexadecimal characters produced by the tt(OFoldStreambuf) object will be inserted into tt(stream). Optionally the maximum line width (in number of characters) may be specified using tt(width). The (default) value 0 indicates that no line breaks are requested. ) The destructor writes any buffered information to the destination stream and will then flushes the destination stream. manpagesection(MEMBER FUNCTIONS) All members of bf(FBB::OFilterStreambuf), in particular its tt(out()) and tt(open()) members are available, as bf(FBB::OHexStreambuf) inherits from this class. itemization( itb(size_t size() const) This member returns the next column offset where the next hexadecimal character will appear. If a maximum line length is requested and tt(size()) does not return 0 then the last line inserted was not terminated by a tt('\n') character. See also the example below. This member's return value is undefined if no maximum line length was requested. ) manpagesection(PROTECTED MEMBER FUNCTION) The member listed in this section implements the tasks of the comparably named virtual function in the class's private interface. This separates the redefinable interface from the user-interface. The class bf(OHexStreambuf) can, in accordance with Liskov's Substitution Principle, be used as a tt(std:streambuf); but it also offers a facility for classes deriving from bf(OHexStreambuf). This facility is listed here. itemization( itb(int pSync()) The contents of the bf(OHexStreambuf)'s internal buffer is flushed. ) manpagesection(STATIC MEMBER) itemization( itb(std::string text2bin(std::string const &in)) This static member can be used to convert a series of hexadecimal characters generated by a tt(OHexStreambuf) object back to their binary form. E.g, when called as tt(OHexStreambuf::text2bin("736d616c6c206976")) then the returned tt(std::string) will contain 8 characters, having respectively the binary values 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x69, and 0x76. This function does em(not) verify whether its argument is properly formed. A properly formed argument consists of an even number of hexadecimal number characters ('0' until '9', 'a' until 'f' (or uppercase)). For improperly formed arguments the return value is undefined. ) manpagesection(EXAMPLE) verb( #include #include using namespace std; using namespace FBB; int main() { OHexStreambuf ohex(cout, 40); ostream out(&ohex); out << cin.rdbuf(); if (ohex.size()) cout << '\n'; } ) manpagefiles() em(bobcat/ohexstreambuf) - defines the class interface manpageseealso() bf(bobcat)(7), bf(ofilterstreambuf)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/socketbase.yo0000644000175000017500000000656712222576536020253 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::SocketBase)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (Base class for sockets) manpagename(FBB::SocketBase)(Base class for socket-constructing classes) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() This class is a base class for the bf(FBB::ServerSocket) and bf(FBB::ClientSocket) classes. Since it is designed as a base class, all its constructors are protected. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::InetAddress) manpagesection(PROTECTED CONSTRUCTORS) itemization( itb(SocketBase(size_t port)) This constructor creates a bf(SocketBase) to be used with bf(ServerSocket)-objects, listening on tt(port). This constructor throws an tt(Exception) exception if it did not properly complete. itb(SocketBase(std::string const &host, uint16_t port)) This constructor creates a bf(FBB::SocketBase) to be used with a bf(ClientSocket)-object, connecting to tt(hostname), at port `tt(port)'. This constructor throws an tt(Exception) exception if it did not properly complete. itb(SocketBase(int socket, sockaddr_in const &address)) This constructor constructs a bf(FBB::SocketBase) object initializing its socket and bf(FBB::InetAddress) part from available external objects. ) The (public) copy constructor is available. manpagesection(MEMBER FUNCTIONS) All members of bf(FBB::InetAddress) are available, as bf(FBB::SocketBase) inherits from this class. itemization( itb(bool debug() const) This accessor returns bf(true) if the socket's em(debug) (bf(SO_DEBUG)) socket option is active. It throws an bf(FBB::Exception) exception if the status of the debug option could not be determined. itb(bool reuse() const) This accessor returns bf(true) if the socket's em(reuse) (bf(SO_REUSEADDR)) socket option is active. It throws an bf(FBB::Exception) exception if the status of the reuse option could not be determined. itb(void setDebug(bool trueIsOn) const) This member may be used to modify the socket's em(debug) (bf(SO_DEBUG)) socket option. It throws an bf(FBB::Exception) exception if the socket's debug option could not be modified. itb(void setReuse(bool trueIsOn) const) This member may be used to modify the socket's em(reuse) (bf(SO_REUSEADDR)) socket option. It throws an bf(FBB::Exception) exception if the socket's reuse option could not be modified. itb(int socket() const) This accessor returns the bf(FBB::SocketBase)'s socket value. itb(void verify() const) Obsoleted, will be removed in a future Bobcat release. ) manpagesection(EXAMPLE) The classes tt(FBB::ClientSocket) and tt(FBB::ServerSocket) were derived from tt(SocketBase). E.g., verbinclude(../../clientsocket/clientsocket) See the bf(clientsocket)(3bobcat) man-page for an example showing how to use tt(FBB::ClientSocket). manpagefiles() em(bobcat/socketbase) - defines the class interface manpageseealso() bf(bobcat)(7), bf(clientsocket)(3bobcat), bf(inetaddress)(3bobcat), bf(localsocketbase)(3bobcat), bf(serversocket)(3bobcat) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/man/isymcryptstream.yo0000644000175000017500000000764412224222342021365 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::ISymCryptStream)(3bobcat)(_CurYrs_) (libbobcat-dev__CurVers_-x.tar.gz) (Symmetric en- and decryption) manpagename(FBB::ISymCryptStream)(Istream performing symmetric encryption) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat -lcrypto) manpagedescription() bf(FBB::ISymCryptStream) objects may be used to encrypt or decrypt information that is available on a separate tt(std::istream). The tt(class ISymCryptStream) is a class template, using a tt(FBB::CryptType) template non-type parameter. Objects of the class tt(FBB::ISymCryptStream) encrypt the information they receive, objects of the class tt(FBB::ISymCryptStream) decrypt the information they receive. All symmetric encryption methods defined by the OpenSSL library that can be selected by name may be used in combination with tt(EncryptBuf) objects. To select a particular encryption method an identifier is passed to the constructor. E.g., tt("aes-128-cbc") indicating the AES (Rijndael) method, using 128 bit sized keys and blocks using `cbc' mode (see below for an explanation). Refer to the bf(isymcryptstreambuf)(3bobcat) man-page for a descryption of available encryption methods. includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::ISymCryptStreambuf) (private), nl() bf(std::istream) manpagesection(CONSTRUCTOR) itemization( itb(ISymCryptStream( std::istream &in, char const *type, std::string const &key, std::string const &iv, size_t bufSize = 100, size_t filterBufSize = 1000, ENGINE *engine = 0)) This constructor initializes a tt(std::istream) providing it with an tt(FBB::ISymCryptStreambuf) stream buffer. The tt(ISymCryptStreambuf)'s constructor receives all arguments that are passed to this constructor. - tt(ISymCryptStream) objects perform encryption;nl() tt(ISymCryptStream) objects perform decryption;nl() - tt(ISymCryptStream) objects obtain the bytes to encrypt or decrypt from tt(std::istream &in);nl() - The encryption method to use is specified by the tt(type) parameter. E.g., tt("bf-cbc") selects the Blowfish Cipher Block Chaining method;nl() - The symmetric key to use is specified by the tt(key) parameter;nl() - The initialization vector is specified by the tt(iv) parameter;nl() - The tt(FBB::ISymCryptStreambuf) internally used buffer will contain tt(bufSize) characters. The default value is the smallest value that is used. When a smaller tt(bufSize) value is specified, the default value is used;nl() - The internally used tt(IFilterStreambuf) is initialized with a buffer of size tt(filterBufSize), using a lower bound of 100;nl() - The parameter tt(ENGINE) can be used to specify a hardware accelleration engine, as supported by the used encryption/decryption method. Its default argument value indicates that no hardware accelleration is available. ) manpagesection(INHERITED MEMBERS) Since the class uses public derivation from bf(std::istream), all members of this class can be used. manpagesection(EXAMPLE) verbinclude(../../isymcryptstream/driver/driver.cc) manpagefiles() em(bobcat/isymcryptstream) - defines the class interface manpageseealso() bf(bobcat)(7), bf(isymcryptstreambuf)(3bobcat) manpagebugs() Sep/Oct 2013: due to a change in library handling by the linker (cf. lurl(http://fedoraproject.org/wiki/UnderstandingDSOLinkChange) and lurl(https://wiki.debian.org/ToolChain/DSOLinking)) libraries that are indirectly required are no longer automatically linked to your program. With bf(BigInt) this is tt(libcrypto), which requires programs to link to both tt(bobcat) and tt(crypto). includefile(include/trailer) bobcat-3.19.01/documentation/man/mailheaders.yo0000644000175000017500000001606212222576536020375 0ustar frankfrankincludefile(include/header) COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::MailHeaders)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) (SMTP Mail Headers) manpagename(FBB::MailHeaders)(Handles SMTP Mail Headers) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() bf(FBB::MailHeaders) objects extract header lines from e-mail. Reading stops at (and including) the first blank line, which becomes the last element of the bf(FBB::MailHeaders) object, interpreted as a bf(vector). The actual e-mail content is therefore left unread on the file containing the e-mail. Each line stored in a bf(MailHeaders) object represents a complete header line. Headers continuing over multiple input lines are concatenated to a single line retrievable from bf(MailHeaders) objects, separated from each other by tt('\n') (newline) characters. The last line to join a multi-line header is not terminated by a newline character. includefile(include/namespace) manpagesection(INHERITS FROM) - manpagesection(ENUMERATIONS) The following enumerations and enumeration values can be used with the class bf(FBB::MailHeaders): bf(enum Mode)nl() This enumeration defines two values: itemization( itb(READ) When this value is specified at construction time, e-mail is immediately read by the constructor. itb(DONT_READ) When this value is specified at construction time, e-mail is read using the tt(read) member (see below). ) bf(enum Match)nl() This enumeration defines the following values: itemization( itb(FULL) Used by tt(setHeaderIterator) (see below) to indicate that the headers must exactly match a specified header name. itb(INITIAL) Used by tt(setHeaderIterator) (see below) to indicate that the initial part of the headers must match the specified header text. itb(PARTIAL) Used by tt(setHeaderIterator) (see below) to indicate that the headers must contain the specified header text. itb(CASE_FULL) Used by tt(setHeaderIterator) (see below) to indicate that the headers must exactly match a specified header name. The matching is performed case insensititvely. itb(CASE_INITIAL) Used by tt(setHeaderIterator) (see below) to indicate that the initial part of the headers must match the specified header text. The matching is performed case insensititvely. itb(CASE_PARTIAL) Used by tt(setHeaderIterator) (see below) to indicate that the headers must contain the specified header text. The matching is performed case insensititvely. ) manpagesection(NESTED TYPES) The class tt(MailHeaders) defines the following types: itemization( itb(const_iterator) An input iterator returned by tt(begin) and tt(end) (see below) itb(const_reverse_iterator) An reverse input iterator returned by the members tt(rbegin) and tt(rend) (see below) ) itb(const_hdr_iterator) An input iterator returned by the members tt(beginh) and tt(endh) (see below) itb(const_reverse_hdr_iterator) An reverse input iterator returned by the members tt(rbeginh) and tt(rendh) (see below) ) Objects of these two iterator types point to header lines. Their derefenced type is tt(std::string). manpagesection(CONSTRUCTORS) itemization( itb(MailHeaders(std::istream &in, Mode mode = READ)) This constructor defines the file containing the e-mail to be processed. The second parameter is by default bf(MailHeaders::READ), causing the object to start reading the e-mail immediately. If set to bf(MailHeaders::DONT_READ), the e-mail is not read. In that case the member tt(read) can be called to process the e-mail later. ) The copy and move constructors are available. manpagesection(OVERLOADED OPERATORS) itemization( itb(std::string const &operator[](size_t idx) const) Returns the tt(idx)-th header line ) The move assignment operator is available manpagesection(MEMBER FUNCTIONS) itemization( itb(const_iterator begin() const) Returns an iterator to the first line of the mail headers. itb(const_hdr_iterator beginh() const) Returns the begin-iterator corresponding to the first header selected by the tt(setHeaderIterator) member. itb(const_iterator end() const) Returns an iterator beyond the last line of the mail headers. itb(const_hdr_iterator endh() const) Returns the end-iterator matching tt(beginh). Note that the member function's name ends in tt(h), to distinguish it from the tt(vector::end) member. itb(const_reverse_iterator rbegin() const) Returns an iterator to the last line of the mail headers. itb(const_reverse_hdr_iterator rbeginh() const) Returns the reversed begin-iterator corresponding to the last header selected by the tt(setHeaderIterator) member. itb(void read()) Reads the mail-headers from the file passed to the bf(FBB::MailHeaders) object's constructor. An bf(FBB::Exception) object is thrown if the mailheaders were already read or if the file is incomplete (i.e., the (obligatory) blank line wasn't found). itb(const_iterator rend() const) Returns an iterator before the first line of the mail headers. itb(const_reverse_hdr_iterator rendh() const) Returns the reversed end-iterator matching tt(rbeginh). itb(void setHeaderIterator(char const *header, Match match = FULL)) Sets the header-iterators to the specified tt(header). The parameter tt(match) defines the match-type to use when selecting headers. The default bf(FBB::MailHeaders::FULL), indicates that the text provided in tt(header) must match exactly an e-mail header. nl() When matching headers the colon terminating the header is em(not) considered and should therefore em(not) be specified by tt(setHeaderIterator). nl() Alternative matching strategies are used when other values of the enumeration bf(FBB::Match) are specified.nl() The member tt(setHeaderIterator) em(must) have been called at least once or the members tt(beginh) and tt(rendh) will throw an bf(FBB::Exception) exception. An bf(FBB::Exception) exception is also thrown if tt(setHeaderIterator) is called when no mail headers are available. itb(size_t size() const) Returns the number of header lines ) manpagesection(EXAMPLE) The following example shows the normal use of these members: verb( // create a MailHeader object MailHeaders mh(cin, MailHeaders::DONT_READ); try { // read the headers mh.read(); } catch (Exception &err) { cout << err.what() << endl; } cout << "There are " << mh.size() << " header lines\n"; // look for the Received: headers mh.setHeaderIterator("Received"); // show the Received headers copy(mh.beginh(), mh.endh(), ostream_iterator(cout, "\n")); ) manpagefiles() em(bobcat/mailheaders) - defines the class interface manpageseealso() bf(bobcat)(7) manpagebugs() None Reported. includefile(include/trailer) bobcat-3.19.01/documentation/examples/0000755000175000017500000000000011714560544016601 5ustar frankfrankbobcat-3.19.01/documentation/examples/sockets/0000755000175000017500000000000012222576536020257 5ustar frankfrankbobcat-3.19.01/documentation/examples/sockets/server/0000755000175000017500000000000012222576536021565 5ustar frankfrankbobcat-3.19.01/documentation/examples/sockets/server/build0000755000175000017500000003747412222576536022631 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/server // script generated by the C++ icmake script version 2.31 /* Configurable defines: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BISON_FLAGS: This directive is only used when a grammar is generated using bison++. It defines the set of flags that are given to bison++ when bison++ generates the parser. By default the following flags are specified: -v -l The -d and -o flags are always provided (not configurable) BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (by default it is defined to the name of the program to be created). COMPILER: The compiler to use. COPT: C-options used by COMPILER LOPT: Define this (default: to "`wx-config --lib`") if a wxWindows program is constructed. In that case, you probably also want to define the COPT option `wx-config --cxxflags`, using, e.g., the following definition: #define COPT "-Wall `wx-config --cxxflags`" ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) GRAMMAR_LINES: When this directive is defined, #line directives will be generated at the first C++ compound statement in each individual grammar specification file. Undefine if no such #line directives are required. LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM "server" #define COMPILER "g++" #define COPT "-Wall" //#define LOPT "`wx-config --libs`" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current, // contains name of current dir. programname; // the name of the program to create int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); #ifdef GRAMMAR_LINES system("./grambuild lines"); #else system("./grambuild"); #endif chdir(".."); if ( exists("grammar") && "grammar" younger "parse.cc" ) // new parser needed #ifdef BISON_FLAGS exec("bisonc++", BISON_FLAGS, "grammar"); #else exec("bisonc++", "grammar"); #endif chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || ( exists("../parser/parser.h") && "../parser/parser.h" younger "yylex.cc" ) ) ) exec("flex", interactive, "lexer"); chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; programname = BUILD_PROGRAM; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD if (exists("parser")) // subdir parser exists { CLASSES += "parser "; parser(); } if (exists("scanner")) // subdir scanner exists { CLASSES += "scanner "; scanner(); } #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library) { printf("\n"); exec(COMPILER, "-o", programname, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifdef LOPT , LOPT #endif #ifndef GDB , "-s" #endif ); printf("ok: ", programname, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "server.cc", // program source "server" // static program library ); #else cpp_make ( "", "server" // static- or so-library ); #endif } bobcat-3.19.01/documentation/examples/sockets/server/server.cc0000644000175000017500000000243712222576536023410 0ustar frankfrank/* server.cc */ #include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) try { if (argc == 1) { cout << "port number required\n"; return 1; } size_t portnr = A2x(argv[1]); ServerSocket server(portnr); server.listen(); // plain blocking listen-mode while (true) { SocketBase fdb = server.accept(); // wait for incoming int fd = fdb.socket(); cerr << "Client FD = " << fd << ", " << endl << "address = " << fdb.dottedDecimalAddress() << ", " << endl << "communication through port " << fdb.port() << endl; IFdStream in(fd); // stream to read from client string cmd; if (getline(in, cmd)) { cout << "Got: " << cmd << endl; if (cmd[0] == 'q') // terminate if client sends `q' return 0; close(fd); // the connection is terminated } } } catch(Errno const &error) { cerr << error.why() << endl; return 1; } bobcat-3.19.01/documentation/examples/sockets/forkserver2/0000755000175000017500000000000012222576536022531 5ustar frankfrankbobcat-3.19.01/documentation/examples/sockets/forkserver2/build0000755000175000017500000003753412222576536023572 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/forkserver2 // script generated by the C++ icmake script version 2.31 /* Configurable defines: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += "handler "; } /* Default values for the following variables are found in $IM/default/defines.im BISON_FLAGS: This directive is only used when a grammar is generated using bison++. It defines the set of flags that are given to bison++ when bison++ generates the parser. By default the following flags are specified: -v -l The -d and -o flags are always provided (not configurable) BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (by default it is defined to the name of the program to be created). COMPILER: The compiler to use. COPT: C-options used by COMPILER LOPT: Define this (default: to "`wx-config --lib`") if a wxWindows program is constructed. In that case, you probably also want to define the COPT option `wx-config --cxxflags`, using, e.g., the following definition: #define COPT "-Wall `wx-config --cxxflags`" ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) GRAMMAR_LINES: When this directive is defined, #line directives will be generated at the first C++ compound statement in each individual grammar specification file. Undefine if no such #line directives are required. LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM "forkserver2" #define COMPILER "g++" #define COPT "-Wall" //#define LOPT "`wx-config --libs`" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current, // contains name of current dir. programname; // the name of the program to create int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); #ifdef GRAMMAR_LINES system("./grambuild lines"); #else system("./grambuild"); #endif chdir(".."); if ( exists("grammar") && "grammar" younger "parse.cc" ) // new parser needed #ifdef BISON_FLAGS exec("bisonc++", BISON_FLAGS, "grammar"); #else exec("bisonc++", "grammar"); #endif chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || ( exists("../parser/parser.h") && "../parser/parser.h" younger "yylex.cc" ) ) ) exec("flex", interactive, "lexer"); chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; programname = BUILD_PROGRAM; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD if (exists("parser")) // subdir parser exists { CLASSES += "parser "; parser(); } if (exists("scanner")) // subdir scanner exists { CLASSES += "scanner "; scanner(); } #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library) { printf("\n"); exec(COMPILER, "-o", programname, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifdef LOPT , LOPT #endif #ifndef GDB , "-s" #endif ); printf("ok: ", programname, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "forkserver2.cc", // program source "forkserver2" // static program library ); #else cpp_make ( "", "forkserver2" // static- or so-library ); #endif } bobcat-3.19.01/documentation/examples/sockets/forkserver2/forkserver2.cc0000644000175000017500000000360112222576536025312 0ustar frankfrank/* forkserver2.cc */ #include #include #include #include #include #include #include #include "handler/handler.h" using namespace std; using namespace FBB; void sigchld_handler(int signum) { static bool stop = false; int status; int pid = waitpid(WAIT_ANY, &status, WNOHANG); if (pid <= 0) // ignore erroroneus or no child available but { cerr << "waitpid() returned " << pid << ", ignoring\n"; return; // the handler is still called. } stop = (WEXITSTATUS(status) != 0); cerr << "Process " << pid << " returns exit status " << WEXITSTATUS(status) << ", stop = " << stop << endl; if (stop) // terminate when done exit(0); } int main(int argc, char **argv, char **envp) try { if (argc == 1) { cout << "port number required\n"; return 1; } signal(SIGCHLD, sigchld_handler); // handle terminating children size_t portnr = A2x(argv[1]); ServerSocket server(portnr); server.listen(); // plain blocking listen-mode while (true) { cerr << "\n" "Wait for incoming requests..." << endl; SocketBase fdb = server.accept(); // wait for incoming int fd = fdb.socket(); cerr << "Client FD = " << fd << ", " << endl << "address = " << fdb.dottedDecimalAddress() << ", " << endl << "communication through port " << fdb.port() << endl; Handler handler(fd); // create separate process for each handler.fork(); // connection } } catch(Errno const &error) { cerr << error.why() << endl; return 1; } bobcat-3.19.01/documentation/examples/sockets/forkserver2/handler/0000755000175000017500000000000012222576536024146 5ustar frankfrankbobcat-3.19.01/documentation/examples/sockets/forkserver2/handler/handler.ih0000644000175000017500000000024012222576536026101 0ustar frankfrank#include "handler.h" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/documentation/examples/sockets/forkserver2/handler/handler.h0000644000175000017500000000062312222576536025735 0ustar frankfrank#ifndef INCLUDED_HANDLER_ #define INCLUDED_HANDLER_ #include class Handler: public FBB::Fork { size_t d_descriptor; public: Handler(size_t descriptor) : d_descriptor(descriptor) {} private: virtual void childProcess(); virtual void parentProcess() { close (d_descriptor); } }; #endif bobcat-3.19.01/documentation/examples/sockets/forkserver2/handler/chidlprocess.cc0000644000175000017500000000125412222576536027141 0ustar frankfrank#include "handler.ih" void Handler::childProcess() try { IFdStream in(d_descriptor); // stream to read from client OFdStream out(d_descriptor); // stream to write to client string cmd; while (getline(in, cmd)) { cout << "Got: " << cmd << endl; out << "Got: " << cmd << "\r" << endl; if (cmd[0] == 'q') throw 1; // terminate the server } throw 0; } catch (int ret) { close(d_descriptor); // the connection is terminated cerr << "Child process " << getpid() << " exits with status " << ret << endl; exit(ret); } bobcat-3.19.01/documentation/examples/sockets/client/0000755000175000017500000000000012222576536021535 5ustar frankfrankbobcat-3.19.01/documentation/examples/sockets/client/build0000755000175000017500000003747412222576536022601 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/client // script generated by the C++ icmake script version 2.31 /* Configurable defines: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BISON_FLAGS: This directive is only used when a grammar is generated using bison++. It defines the set of flags that are given to bison++ when bison++ generates the parser. By default the following flags are specified: -v -l The -d and -o flags are always provided (not configurable) BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (by default it is defined to the name of the program to be created). COMPILER: The compiler to use. COPT: C-options used by COMPILER LOPT: Define this (default: to "`wx-config --lib`") if a wxWindows program is constructed. In that case, you probably also want to define the COPT option `wx-config --cxxflags`, using, e.g., the following definition: #define COPT "-Wall `wx-config --cxxflags`" ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) GRAMMAR_LINES: When this directive is defined, #line directives will be generated at the first C++ compound statement in each individual grammar specification file. Undefine if no such #line directives are required. LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM "client" #define COMPILER "g++" #define COPT "-Wall" //#define LOPT "`wx-config --libs`" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current, // contains name of current dir. programname; // the name of the program to create int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); #ifdef GRAMMAR_LINES system("./grambuild lines"); #else system("./grambuild"); #endif chdir(".."); if ( exists("grammar") && "grammar" younger "parse.cc" ) // new parser needed #ifdef BISON_FLAGS exec("bisonc++", BISON_FLAGS, "grammar"); #else exec("bisonc++", "grammar"); #endif chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || ( exists("../parser/parser.h") && "../parser/parser.h" younger "yylex.cc" ) ) ) exec("flex", interactive, "lexer"); chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; programname = BUILD_PROGRAM; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD if (exists("parser")) // subdir parser exists { CLASSES += "parser "; parser(); } if (exists("scanner")) // subdir scanner exists { CLASSES += "scanner "; scanner(); } #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library) { printf("\n"); exec(COMPILER, "-o", programname, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifdef LOPT , LOPT #endif #ifndef GDB , "-s" #endif ); printf("ok: ", programname, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "client.cc", // program source "client" // static program library ); #else cpp_make ( "", "client" // static- or so-library ); #endif } bobcat-3.19.01/documentation/examples/sockets/client/client.cc0000644000175000017500000000251712222576536023327 0ustar frankfrank/* client.cc */ #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc != 3) { cerr << "Provide servername and port number\n"; return 1; } size_t port = A2x(argv[2]); ClientSocket client(argv[1], port); int fd = client.connect(); string line; cout << "Connecting to socket " << fd << endl << "address = " << client.dottedDecimalAddress() << ", " << endl << "communication through port " << client.port() << endl; OFdStream out(fd); // stream to write to while (true) { // Ask for a textline, stop if cout << "? "; // empty / none if (!getline(cin, line) || line.length() == 0) return 0; cout << "Line read: " << line << endl; // Send the line to the server out << line.c_str() << endl; cout << "wrote line\n"; } return 0; } catch (Errno const &err) { cerr << err.why() << "\n" << "Can't connect to " << argv[1] << ", port " << argv[2] << endl; return 1; } bobcat-3.19.01/documentation/examples/sockets/README0000644000175000017500000000621412222576536021142 0ustar frankfrankThe directories below this one contain various programs illustrating the CLientSocket and ServerSocket classes. To compile the programs, descend into the directories and run the `build' script. Icmake must be available to run `build'. The following programs are available: - server - simple server program, serving one client at the time. Start the server as server where is the port at which the server will listen for incoming connections. E.g., server 12345 The communication protocol is extremely simple: the server expects a single line from the client, echoes the line and terminates the connection. If the line holds a single `q' the server itself will terminate. - client - simple client program, matching the abovementioned server. Start the client as client where is the name of the computer running the server, and is the port at which the server will listen for incoming connections. E.g., client localhost 12345 - forkserver - simple server program, serving multiple clients, each running as its own independent process. It implements the same protocol as `server', mentioned above. Start the server as forkserver where is the port at which the server will listen for incoming connections. E.g., forkserver 12345 Use the client defined in the `client' subdirectory. - forkserver2 - server program, serving multiple clients, each running as its own independent process. It implements a more complex protocol than `forkserver' Start the server as forkserver2 where is the port at which the server will listen for incoming connections. E.g., forkserver2 12345 The protocol allows for 2-way communication between client(s) and server. The server will start an independent process for each new client, and these processes will echo lines received from clients back to the clients. If a client sends a line holding a single `q', the server process terminates. Use the `client2' program (see below) with this server. - client2 - client program, matching the abovementioned server. Start the client as client2 where is the name of the computer running the server, and is the port at which the server will listen for incoming connections. E.g., client2 localhost 12345 bobcat-3.19.01/documentation/examples/sockets/forkserver/0000755000175000017500000000000012222576536022447 5ustar frankfrankbobcat-3.19.01/documentation/examples/sockets/forkserver/build0000755000175000017500000003752712222576536023512 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/forkserver // script generated by the C++ icmake script version 2.31 /* Configurable defines: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += "handler "; } /* Default values for the following variables are found in $IM/default/defines.im BISON_FLAGS: This directive is only used when a grammar is generated using bison++. It defines the set of flags that are given to bison++ when bison++ generates the parser. By default the following flags are specified: -v -l The -d and -o flags are always provided (not configurable) BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (by default it is defined to the name of the program to be created). COMPILER: The compiler to use. COPT: C-options used by COMPILER LOPT: Define this (default: to "`wx-config --lib`") if a wxWindows program is constructed. In that case, you probably also want to define the COPT option `wx-config --cxxflags`, using, e.g., the following definition: #define COPT "-Wall `wx-config --cxxflags`" ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) GRAMMAR_LINES: When this directive is defined, #line directives will be generated at the first C++ compound statement in each individual grammar specification file. Undefine if no such #line directives are required. LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM "forkserver" #define COMPILER "g++" #define COPT "-Wall" //#define LOPT "`wx-config --libs`" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current, // contains name of current dir. programname; // the name of the program to create int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); #ifdef GRAMMAR_LINES system("./grambuild lines"); #else system("./grambuild"); #endif chdir(".."); if ( exists("grammar") && "grammar" younger "parse.cc" ) // new parser needed #ifdef BISON_FLAGS exec("bisonc++", BISON_FLAGS, "grammar"); #else exec("bisonc++", "grammar"); #endif chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || ( exists("../parser/parser.h") && "../parser/parser.h" younger "yylex.cc" ) ) ) exec("flex", interactive, "lexer"); chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; programname = BUILD_PROGRAM; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD if (exists("parser")) // subdir parser exists { CLASSES += "parser "; parser(); } if (exists("scanner")) // subdir scanner exists { CLASSES += "scanner "; scanner(); } #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library) { printf("\n"); exec(COMPILER, "-o", programname, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifdef LOPT , LOPT #endif #ifndef GDB , "-s" #endif ); printf("ok: ", programname, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "forkserver.cc", // program source "forkserver" // static program library ); #else cpp_make ( "", "forkserver" // static- or so-library ); #endif } bobcat-3.19.01/documentation/examples/sockets/forkserver/forkserver.cc0000644000175000017500000000360012222576536025145 0ustar frankfrank/* forkserver.cc */ #include #include #include #include #include #include #include #include "handler/handler.h" using namespace std; using namespace FBB; void sigchld_handler(int signum) { static bool stop = false; int status; int pid = waitpid(WAIT_ANY, &status, WNOHANG); if (pid <= 0) // ignore erroroneus or no child available but { cerr << "waitpid() returned " << pid << ", ignoring\n"; return; // the handler is still called. } stop = (WEXITSTATUS(status) != 0); cerr << "Process " << pid << " returns exit status " << WEXITSTATUS(status) << ", stop = " << stop << endl; if (stop) // terminate when done exit(0); } int main(int argc, char **argv, char **envp) try { if (argc == 1) { cout << "port number required\n"; return 1; } signal(SIGCHLD, sigchld_handler); // handle terminating children size_t portnr = A2x(argv[1]); ServerSocket server(portnr); server.listen(); // plain blocking listen-mode while (true) { cerr << "\n" "Wait for incoming requests..." << endl; SocketBase fdb = server.accept(); // wait for incoming int fd = fdb.socket(); cerr << "Client FD = " << fd << ", " << endl << "address = " << fdb.dottedDecimalAddress() << ", " << endl << "communication through port " << fdb.port() << endl; Handler handler(fd); // create separate process for each handler.fork(); // connection } } catch(Errno const &error) { cerr << error.why() << endl; return 1; } bobcat-3.19.01/documentation/examples/sockets/forkserver/handler/0000755000175000017500000000000012222576536024064 5ustar frankfrankbobcat-3.19.01/documentation/examples/sockets/forkserver/handler/handler.ih0000644000175000017500000000020412222576536026017 0ustar frankfrank#include "handler.h" #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/documentation/examples/sockets/forkserver/handler/handler.h0000644000175000017500000000062312222576536025653 0ustar frankfrank#ifndef INCLUDED_HANDLER_ #define INCLUDED_HANDLER_ #include class Handler: public FBB::Fork { size_t d_descriptor; public: Handler(size_t descriptor) : d_descriptor(descriptor) {} private: virtual void childProcess(); virtual void parentProcess() { close (d_descriptor); } }; #endif bobcat-3.19.01/documentation/examples/sockets/forkserver/handler/chidlprocess.cc0000644000175000017500000000111012222576536027046 0ustar frankfrank#include "handler.ih" void Handler::childProcess() try { IFdStream in(d_descriptor); // stream to read from client string cmd; if (getline(in, cmd)) { cerr << "Child process gets: `" << cmd << "'" << endl; if (cmd[0] != 'q') // terminate if client sends `q' throw 0; } throw 1; } catch (int ret) { close(d_descriptor); // the connection is terminated cerr << "Child process " << getpid() << " exits with status " << ret << endl; exit(ret); } bobcat-3.19.01/documentation/examples/sockets/client2/0000755000175000017500000000000012222576536021617 5ustar frankfrankbobcat-3.19.01/documentation/examples/sockets/client2/build0000755000175000017500000003750112222576536022652 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/client2 // script generated by the C++ icmake script version 2.31 /* Configurable defines: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BISON_FLAGS: This directive is only used when a grammar is generated using bison++. It defines the set of flags that are given to bison++ when bison++ generates the parser. By default the following flags are specified: -v -l The -d and -o flags are always provided (not configurable) BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (by default it is defined to the name of the program to be created). COMPILER: The compiler to use. COPT: C-options used by COMPILER LOPT: Define this (default: to "`wx-config --lib`") if a wxWindows program is constructed. In that case, you probably also want to define the COPT option `wx-config --cxxflags`, using, e.g., the following definition: #define COPT "-Wall `wx-config --cxxflags`" ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) GRAMMAR_LINES: When this directive is defined, #line directives will be generated at the first C++ compound statement in each individual grammar specification file. Undefine if no such #line directives are required. LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM "client2" #define COMPILER "g++" #define COPT "-Wall" //#define LOPT "`wx-config --libs`" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current, // contains name of current dir. programname; // the name of the program to create int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); #ifdef GRAMMAR_LINES system("./grambuild lines"); #else system("./grambuild"); #endif chdir(".."); if ( exists("grammar") && "grammar" younger "parse.cc" ) // new parser needed #ifdef BISON_FLAGS exec("bisonc++", BISON_FLAGS, "grammar"); #else exec("bisonc++", "grammar"); #endif chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || ( exists("../parser/parser.h") && "../parser/parser.h" younger "yylex.cc" ) ) ) exec("flex", interactive, "lexer"); chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; programname = BUILD_PROGRAM; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD if (exists("parser")) // subdir parser exists { CLASSES += "parser "; parser(); } if (exists("scanner")) // subdir scanner exists { CLASSES += "scanner "; scanner(); } #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library) { printf("\n"); exec(COMPILER, "-o", programname, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifdef LOPT , LOPT #endif #ifndef GDB , "-s" #endif ); printf("ok: ", programname, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "client2.cc", // program source "client2" // static program library ); #else cpp_make ( "", "client2" // static- or so-library ); #endif } bobcat-3.19.01/documentation/examples/sockets/client2/client2.cc0000644000175000017500000000303612222576536023470 0ustar frankfrank/* client2.cc */ #include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc != 3) { cerr << "Provide servername and port number\n"; return 1; } size_t port = A2x(argv[2]); ClientSocket client(argv[1], port); int fd = client.connect(); string line; cout << "Connecting to socket " << fd << endl << "address = " << client.dottedDecimalAddress() << ", " << endl << "communication through port " << client.port() << endl; IFdStream in(fd); // stream to read from OFdStream out(fd); // stream to write to while (true) { // Ask for a textline, stop if cout << "? "; // empty / none if (!getline(cin, line) || line.length() == 0) return 0; cout << "Line read: " << line << endl; // Return the line to the server out << line.c_str() << endl; cout << "wrote line\n"; getline(in, line); // Wait for a reply from the server cout << "Answer: " << line << endl; } return 0; } catch (Errno const &err) { cerr << err.why() << "\n" << "Can't connect to " << argv[1] << ", port " << argv[2] << endl; return 1; } bobcat-3.19.01/encryptbuf/0000755000175000017500000000000012257325714014274 5ustar frankfrankbobcat-3.19.01/encryptbuf/encryptbuf1.cc0000644000175000017500000000252512222576534017051 0ustar frankfrank#include "encryptbuf.ih" EncryptBuf::EncryptBuf(ostream &outStream, char const *type, string key, string iv, size_t bufsize) : d_pimpl(new EncryptBufImp(outStream, iv, bufsize)) { try { OpenSSL_add_all_ciphers(); d_pimpl->md = EVP_get_cipherbyname(type); if (!d_pimpl->md) { if (type == 0) type = "** unspecified cipher type **"; throw Exception(1) << "EncryptBuf `" << type << "' not available"; } size_t keyLength = key.length(); if (keyLength > EVP_MAX_KEY_LENGTH) keyLength = EVP_MAX_KEY_LENGTH; key.resize(EVP_MAX_KEY_LENGTH); iv.resize(EVP_MAX_IV_LENGTH); EVP_CIPHER_CTX_init(&d_pimpl->ctx); if ( !EVP_EncryptInit_ex(&d_pimpl->ctx, d_pimpl->md, 0, 0, // no key yet, is entered next reinterpret_cast(iv.data())) ) throw Exception(1) << "EncryptBuf: initialization failed"; installKey(key, keyLength); d_pimpl->buffer = new char[bufsize]; d_pimpl->out = new char[ bufsize + EVP_CIPHER_CTX_block_size(&d_pimpl->ctx)]; open(); } catch (...) { delete d_pimpl; throw; } } bobcat-3.19.01/encryptbuf/iv.cc0000644000175000017500000000014012222576534015214 0ustar frankfrank#include "encryptbuf.ih" std::string const &EncryptBuf::iv() const { return d_pimpl->iv; } bobcat-3.19.01/encryptbuf/setkey.cc0000644000175000017500000000050212222576534016104 0ustar frankfrank#include "encryptbuf.ih" void EncryptBuf::setKey(string key, size_t numberOfBytes) { if (d_pimpl->active) throw Exception(1) << "Can't change Key during encryption"; if (numberOfBytes == 0) numberOfBytes = key.length(); key.resize(EVP_MAX_KEY_LENGTH); installKey(key, numberOfBytes); } bobcat-3.19.01/encryptbuf/keylength.cc0000644000175000017500000000017012222576534016573 0ustar frankfrank#include "encryptbuf.ih" size_t EncryptBuf::keyLength() const { return EVP_CIPHER_CTX_key_length(&d_pimpl->ctx); } bobcat-3.19.01/encryptbuf/ivlength.cc0000644000175000017500000000016612222576534016426 0ustar frankfrank#include "encryptbuf.ih" size_t EncryptBuf::ivLength() const { return EVP_CIPHER_CTX_iv_length(&d_pimpl->ctx); } bobcat-3.19.01/encryptbuf/destructor.cc0000644000175000017500000000042012222576534016775 0ustar frankfrank#include "encryptbuf.ih" EncryptBuf::~EncryptBuf() { update(); int outLen; EVP_EncryptFinal_ex(&d_pimpl->ctx, reinterpret_cast(d_pimpl->out), &outLen); d_pimpl->outStream.write(d_pimpl->out, outLen); delete d_pimpl; } bobcat-3.19.01/encryptbuf/setchar.cc0000644000175000017500000000020712222576534016233 0ustar frankfrank#include "encryptbuf.ih" void EncryptBufImp::setChar(char &ch, IRandStream &irs) { int value; irs >> value; ch = value; } bobcat-3.19.01/encryptbuf/destructor.f0000644000175000017500000000012412223023055016620 0ustar frankfrankinline EncryptBufImp::~EncryptBufImp() { delete [] buffer; delete [] out; } bobcat-3.19.01/encryptbuf/encryptbufimp.cc0000644000175000017500000000065512222576534017500 0ustar frankfrank#include "encryptbuf.ih" EncryptBufImp::EncryptBufImp(ostream &outStream, string const &ivv, size_t bufsize) : active(false), bufsize(bufsize), buffer(0), out(0), iv(ivv), outStream(outStream) { if (iv.empty()) { iv.resize(EVP_MAX_IV_LENGTH); IRandStream irs(0, 255, time(0)); for (auto &ch: iv) setChar(ch, irs); } } bobcat-3.19.01/encryptbuf/open.cc0000644000175000017500000000016612222576534015547 0ustar frankfrank#include "encryptbuf.ih" void EncryptBuf::open() { setp(d_pimpl->buffer, d_pimpl->buffer + d_pimpl->bufsize); } bobcat-3.19.01/encryptbuf/encryptbuf.ih0000644000175000017500000000140712223023055016763 0ustar frankfrank#include "encryptbuf" #include #include #include #include #include #include #include namespace FBB { struct EncryptBufImp { EVP_CIPHER_CTX ctx; EVP_CIPHER const *md; bool active; size_t bufsize; char *buffer; char *out; std::string iv; std::ostream &outStream; EncryptBufImp(std::ostream &outStream, std::string const &iv, size_t bufsize); ~EncryptBufImp(); // destructor.i static void setChar(char &ch, IRandStream &irs); }; #include "destructor.f" } // FBB using namespace std; using namespace FBB; bobcat-3.19.01/encryptbuf/setiv.cc0000644000175000017500000000061712222576534015741 0ustar frankfrank#include "encryptbuf.ih" void EncryptBuf::setIv(string iv) { if (d_pimpl->active) throw Exception(1) << "Can't change IV during encryption"; d_pimpl->iv = iv; iv.resize(EVP_MAX_IV_LENGTH); if ( !EVP_EncryptInit_ex(&d_pimpl->ctx, 0, 0, 0, reinterpret_cast(iv.data())) ) throw Exception(1) << "Couldn't set IV"; } bobcat-3.19.01/encryptbuf/setrounds.cc0000644000175000017500000000033612222576534016633 0ustar frankfrank#include "encryptbuf.ih" bool EncryptBuf::setRounds(size_t nRounds) { return EVP_CIPHER_CTX_ctrl(&d_pimpl->ctx, EVP_CTRL_SET_RC5_ROUNDS, nRounds, 0); } bobcat-3.19.01/encryptbuf/driver/0000755000175000017500000000000012224222573015560 5ustar frankfrankbobcat-3.19.01/encryptbuf/driver/build0000755000175000017500000000130212222576534016610 0ustar frankfrank#!/bin/bash # ln -s .. bobcat # ln -s ../ohexstreambuf/ohexstreambuf bobcat # # g++ -I. --std=c++0x -O2 -Wall -o driver driver.cc -lssl -lbobcat \ # -L../../ohexstreambuf/tmp -L../tmp -lencryptbuf -lohexstreambuf # # rm bobcat/ohexstreambuf bobcat # echo g++ --std=c++0x -O2 -Wall -o driver driver.cc -lbobcat # g++ --std=c++0x -O2 -Wall -o driver driver.cc -lbobcat # echo g++ -I. --std=c++0x -O2 -Wall -o driver driver.cc -L../tmp -lencryptbuf \ # -lssl -lbobcat # # g++ -I. --std=c++0x -O2 -Wall -o driver driver.cc -L../tmp -lencryptbuf \ # -lssl -lbobcat tput clear LIBS=" -lbobcat" GPP="g++ --std=c++0x" CMD="$GPP -o driver -Wall *.cc ${LIBS} -s" echo ${CMD} ${CMD} bobcat-3.19.01/encryptbuf/driver/driver.cc0000644000175000017500000000213012222576534017365 0ustar frankfrank#include #include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) throw Errno("1st arg: method, 2nd arg: key, 3rd arg: (opt): iv, " "stdin: file to encrypt (to stdout)"); string key(argv[2]); string iv; if (argc > 3) iv = argv[3]; EncryptBuf encryptbuf(cout, argv[1], key, iv); ostream out(&encryptbuf); cerr << "Block length: " << encryptbuf.blockLength() << '\n' << "Key length: " << encryptbuf.keyLength() << '\n' << "Max Key length: " << EVP_MAX_KEY_LENGTH << '\n' << "IV length: " << encryptbuf.ivLength() << endl; cerr << encryptbuf.iv().length() << ' '; OHexStreambuf ohsb(cerr); ostream ohs(&ohsb); ohs.write(encryptbuf.iv().data(), encryptbuf.iv().length()) << flush; cerr << endl; out << cin.rdbuf(); } catch(Errno const &err) { cout << err.why() << endl; return 1; } bobcat-3.19.01/encryptbuf/cipherctx.cc0000644000175000017500000000014012222576534016567 0ustar frankfrank#include "encryptbuf.ih" EVP_CIPHER_CTX *EncryptBuf::cipherCtx() { return &d_pimpl->ctx; } bobcat-3.19.01/encryptbuf/encryptbuf0000644000175000017500000002334412222576534016406 0ustar frankfrank#ifndef INCLUDED_BOBCAT_ENCRYPTBUF_ #define INCLUDED_BOBCAT_ENCRYPTBUF_ #include #include #include namespace FBB { struct EncryptBufImp; class EncryptBuf: public std::streambuf { EncryptBufImp *d_pimpl; public: EncryptBuf(std::ostream &outStream, char const *type, std::string key, std::string iv, size_t bufsize = 1024); virtual ~EncryptBuf(); void setKey(std::string key, size_t numberOfBytes = 0); void setIv(std::string iv); size_t keyLength() const; // bytes size_t blockLength() const; // bytes size_t ivLength() const; // bytes bool setRounds(size_t nRounds); // RC5 8, 12 or 16 size_t rounds() const; // RC5 std::string const &iv() const; protected: EVP_CIPHER_CTX *cipherCtx(); private: void update(); void open(); void installKey(std::string const &key, size_t length); virtual int overflow(int c); }; } // FBB /* EVP_enc_null() Null cipher: does nothing. DES: Avoid, unless required, uses 8 byte buffer and 8 byte key EVP_des_cbc(), EVP_des_ecb(), EVP_des_cfb(), EVP_des_ofb() DES in CBC, ECB, CFB and OFB modes respectively. 3DES: Uses 8 byte buffer and 2x8 byte key for the two keys EVP_des_ede_cbc(), EVP_des_ede(), EVP_des_ede_ofb(), EVP_des_ede_cfb() Two key triple DES in CBC, ECB, CFB and OFB modes respectively. 3DES 3keys: Uses 8 byte buffer and 3x8 byte key for the 3 8 byte keys. EVP_des_ede3_cbc(), EVP_des_ede3(), EVP_des_ede3_ofb(), EVP_des_ede3_cfb() Three key triple DES in CBC, ECB, CFB and OFB modes respectively. DESX: --> BOOK !! EVP_desx_cbc() DESX algorithm in CBC mode. const EVP_CIPHER *EVP_des_ecb(); const EVP_CIPHER *EVP_des_ede(); const EVP_CIPHER *EVP_des_ede3(); const EVP_CIPHER *EVP_des_ede_ecb(); const EVP_CIPHER *EVP_des_ede3_ecb(); const EVP_CIPHER *EVP_des_cfb64(); # define EVP_des_cfb EVP_des_cfb64 const EVP_CIPHER *EVP_des_cfb1(); const EVP_CIPHER *EVP_des_cfb8(); const EVP_CIPHER *EVP_des_ede_cfb64(); # define EVP_des_ede_cfb EVP_des_ede_cfb64 #if 0 const EVP_CIPHER *EVP_des_ede_cfb1(); const EVP_CIPHER *EVP_des_ede_cfb8(); #endif const EVP_CIPHER *EVP_des_ede3_cfb64(); # define EVP_des_ede3_cfb EVP_des_ede3_cfb64 const EVP_CIPHER *EVP_des_ede3_cfb1(); const EVP_CIPHER *EVP_des_ede3_cfb8(); const EVP_CIPHER *EVP_des_ofb(); const EVP_CIPHER *EVP_des_ede_ofb(); const EVP_CIPHER *EVP_des_ede3_ofb(); const EVP_CIPHER *EVP_des_cbc(); const EVP_CIPHER *EVP_des_ede_cbc(); const EVP_CIPHER *EVP_des_ede3_cbc(); const EVP_CIPHER *EVP_desx_cbc(); RC4: EVP_rc4() RC4 stream cipher. This is a variable key length cipher with default key length 128 bits. #ifndef OPENSSL_NO_RC4 const EVP_CIPHER *EVP_rc4(); const EVP_CIPHER *EVP_rc4_40(); #endif RC4_40: EVP_rc4_40() RC4 stream cipher with 40 bit key length. This is obsolete and new code should use EVP_rc4() and the EVP_CIPHER_CTX_set_key_length() function. IDEA: EVP_idea_cbc(), EVP_idea_ecb(), EVP_idea_cfb(), EVP_idea_ofb() IDEA encryption algorithm in CBC, ECB, CFB and OFB modes respectively. #ifndef OPENSSL_NO_IDEA const EVP_CIPHER *EVP_idea_ecb(); const EVP_CIPHER *EVP_idea_cfb64(); # define EVP_idea_cfb EVP_idea_cfb64 const EVP_CIPHER *EVP_idea_ofb(); const EVP_CIPHER *EVP_idea_cbc(); #endif RC2: EVP_rc2_cbc(), EVP_rc2_ecb(), EVP_rc2_cfb(), EVP_rc2_ofb() RC2 encryption algorithm in CBC, ECB, CFB and OFB modes respectively. This is a variable key length cipher with an additional parameter called "effective key bits" or "effective key length". By default both are set to 128 bits. #ifndef OPENSSL_NO_RC2 const EVP_CIPHER *EVP_rc2_ecb(); const EVP_CIPHER *EVP_rc2_cbc(); const EVP_CIPHER *EVP_rc2_40_cbc(); const EVP_CIPHER *EVP_rc2_64_cbc(); const EVP_CIPHER *EVP_rc2_cfb64(); # define EVP_rc2_cfb EVP_rc2_cfb64 const EVP_CIPHER *EVP_rc2_ofb(); #endif RC2-40: RC2-64: EVP_rc2_40_cbc(), EVP_rc2_64_cbc() RC2 algorithm in CBC mode with a default key length and effective key length of 40 and 64 bits. These are obsolete and new code should use EVP_rc2_cbc(), EVP_CIPHER_CTX_set_key_length() and EVP_CIPHER_CTX_ctrl() to set the key length and effective key length. BLOWFISH: EVP_bf_cbc(), EVP_bf_ecb(), EVP_bf_cfb(), EVP_bf_ofb(); Blowfish encryption algorithm in CBC, ECB, CFB and OFB modes respectively. This is a variable key length cipher. #ifndef OPENSSL_NO_BF const EVP_CIPHER *EVP_bf_ecb(); const EVP_CIPHER *EVP_bf_cbc(); const EVP_CIPHER *EVP_bf_cfb64(); # define EVP_bf_cfb EVP_bf_cfb64 const EVP_CIPHER *EVP_bf_ofb(); #endif CAST: EVP_cast5_cbc(), EVP_cast5_ecb(), EVP_cast5_cfb(), EVP_cast5_ofb() CAST encryption algorithm in CBC, ECB, CFB and OFB modes respectively. This is a variable key length cipher. #ifndef OPENSSL_NO_CAST const EVP_CIPHER *EVP_cast5_ecb(); const EVP_CIPHER *EVP_cast5_cbc(); const EVP_CIPHER *EVP_cast5_cfb64(); # define EVP_cast5_cfb EVP_cast5_cfb64 const EVP_CIPHER *EVP_cast5_ofb(); #endif RC5: EVP_rc5_32_12_16_cbc(), EVP_rc5_32_12_16_ecb(), EVP_rc5_32_12_16_cfb(), EVP_rc5_32_12_16_ofb() RC5 encryption algorithm in CBC, ECB, CFB and OFB modes respectively. This is a variable key length cipher with an additional "number of rounds" parameter. By default the key length is set to 128 bits and 12 rounds. #ifndef OPENSSL_NO_RC5 const EVP_CIPHER *EVP_rc5_32_12_16_cbc(); const EVP_CIPHER *EVP_rc5_32_12_16_ecb(); const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(); # define EVP_rc5_32_12_16_cfb EVP_rc5_32_12_16_cfb64 const EVP_CIPHER *EVP_rc5_32_12_16_ofb(); #endif #if 0 # ifdef OPENSSL_OPENBSD_DEV_CRYPTO const EVP_CIPHER *EVP_dev_crypto_des_ede3_cbc(); const EVP_CIPHER *EVP_dev_crypto_rc4(); const EVP_MD *EVP_dev_crypto_md5(); # endif #endif #ifndef OPENSSL_NO_AES const EVP_CIPHER *EVP_aes_128_ecb(); const EVP_CIPHER *EVP_aes_128_cbc(); const EVP_CIPHER *EVP_aes_128_cfb1(); const EVP_CIPHER *EVP_aes_128_cfb8(); const EVP_CIPHER *EVP_aes_128_cfb128(); # define EVP_aes_128_cfb EVP_aes_128_cfb128 const EVP_CIPHER *EVP_aes_128_ofb(); #if 0 const EVP_CIPHER *EVP_aes_128_ctr(); #endif const EVP_CIPHER *EVP_aes_192_ecb(); const EVP_CIPHER *EVP_aes_192_cbc(); const EVP_CIPHER *EVP_aes_192_cfb1(); const EVP_CIPHER *EVP_aes_192_cfb8(); const EVP_CIPHER *EVP_aes_192_cfb128(); # define EVP_aes_192_cfb EVP_aes_192_cfb128 const EVP_CIPHER *EVP_aes_192_ofb(); #if 0 const EVP_CIPHER *EVP_aes_192_ctr(); #endif const EVP_CIPHER *EVP_aes_256_ecb(); const EVP_CIPHER *EVP_aes_256_cbc(); const EVP_CIPHER *EVP_aes_256_cfb1(); const EVP_CIPHER *EVP_aes_256_cfb8(); const EVP_CIPHER *EVP_aes_256_cfb128(); # define EVP_aes_256_cfb EVP_aes_256_cfb128 const EVP_CIPHER *EVP_aes_256_ofb(); const EVP_CIPHER *EVP_aes_256_ctr(); In cryptography, Camellia is a block cipher that has been evaluated favorably by several organisations, including the European Union's NESSIE project (a selected algorithm), and the Japanese CRYPTREC project (a recommended algorithm). The cipher was developed jointly by Mitsubishi and NTT in 2000, and has similar design elements to earlier block ciphers (MISTY1 and E2) from these companies. Camellia has a block size of 128 bits, and can use 128-bit, 192-bit or 256-bit keys - the same interface as the Advanced Encryption Standard. It is a Feistel cipher with either 18 rounds (if the key is 128 bits) or 24 rounds (if the key is 192 or 256 bits). Every six rounds, a logical transformation layer is applied: the so-called "FL-function" or its inverse. Camellia uses four 8 x 8-bit S-boxes with input and output affine transformations and logical operations. The cipher also uses input and output key whitening. The diffusion layer uses a linear transformation based on an MDS matrix with a branch number of 5. On June, 18 2008, support for the adopted Camellia cipher was added to the final release of Mozilla Firefox 3.[citation needed] http://en.wikipedia.org/wiki/Camellia_(cipher) const EVP_CIPHER *EVP_camellia_128_ecb(); const EVP_CIPHER *EVP_camellia_128_cbc(); const EVP_CIPHER *EVP_camellia_128_cfb1(); const EVP_CIPHER *EVP_camellia_128_cfb8(); const EVP_CIPHER *EVP_camellia_128_cfb128(); # define EVP_camellia_128_cfb EVP_camellia_128_cfb128 const EVP_CIPHER *EVP_camellia_128_ofb(); const EVP_CIPHER *EVP_camellia_192_ecb(); const EVP_CIPHER *EVP_camellia_192_cbc(); const EVP_CIPHER *EVP_camellia_192_cfb1(); const EVP_CIPHER *EVP_camellia_192_cfb8(); const EVP_CIPHER *EVP_camellia_192_cfb128(); # define EVP_camellia_192_cfb EVP_camellia_192_cfb128 const EVP_CIPHER *EVP_camellia_192_ofb(); const EVP_CIPHER *EVP_camellia_256_ecb(); const EVP_CIPHER *EVP_camellia_256_cbc(); const EVP_CIPHER *EVP_camellia_256_cfb1(); const EVP_CIPHER *EVP_camellia_256_cfb8(); const EVP_CIPHER *EVP_camellia_256_cfb128(); # define EVP_camellia_256_cfb EVP_camellia_256_cfb128 const EVP_CIPHER *EVP_camellia_256_ofb(); #ifndef OPENSSL_NO_SEED const EVP_CIPHER *EVP_seed_ecb(); const EVP_CIPHER *EVP_seed_cbc(); const EVP_CIPHER *EVP_seed_cfb128(); # define EVP_seed_cfb EVP_seed_cfb128 const EVP_CIPHER *EVP_seed_ofb(); #endif */ #endif bobcat-3.19.01/encryptbuf/blocklength.cc0000644000175000017500000000017212222576534017077 0ustar frankfrank#include "encryptbuf.ih" size_t EncryptBuf::blockLength() const { return EVP_CIPHER_CTX_block_size(&d_pimpl->ctx); } bobcat-3.19.01/encryptbuf/overflow.cc0000644000175000017500000000031012222576534016440 0ustar frankfrank#include "encryptbuf.ih" int EncryptBuf::overflow(int c) { update(); open(); if (c != EOF) { *pptr() = static_cast(c); pbump(1); } return c; } bobcat-3.19.01/encryptbuf/rounds.cc0000644000175000017500000000041112222576534016111 0ustar frankfrank#include "encryptbuf.ih" size_t EncryptBuf::rounds() const { size_t nRounds; return EVP_CIPHER_CTX_ctrl(&d_pimpl->ctx, EVP_CTRL_GET_RC5_ROUNDS, 0, &nRounds) ? nRounds : 0; } bobcat-3.19.01/encryptbuf/installkey.cc0000644000175000017500000000054012222576534016761 0ustar frankfrank#include "encryptbuf.ih" void EncryptBuf::installKey(string const &key, size_t numberOfBytes) { EVP_CIPHER_CTX_set_key_length(&d_pimpl->ctx, numberOfBytes); if ( !EVP_EncryptInit_ex(&d_pimpl->ctx, 0, 0, reinterpret_cast(key.data()), 0) ) throw Exception(1) << "Couldn't set Key"; } bobcat-3.19.01/encryptbuf/update.cc0000644000175000017500000000057412222576534016073 0ustar frankfrank#include "encryptbuf.ih" void EncryptBuf::update() { d_pimpl->active = true; int outLen; EVP_EncryptUpdate(&d_pimpl->ctx, reinterpret_cast(d_pimpl->out), &outLen, reinterpret_cast(d_pimpl->buffer), pptr() - pbase()); d_pimpl->outStream.write(d_pimpl->out, outLen); } bobcat-3.19.01/errno/0000755000175000017500000000000012242431634013231 5ustar frankfrankbobcat-3.19.01/errno/open2.cc0000644000175000017500000000042412222576537014575 0ustar frankfrank#include "errno.ih" void Errno::open(std::ofstream &out, std::string const &name, ios::openmode mode) { if (out.is_open()) out.close(); out.open(name.c_str(), mode); if (!out) throw Errno(1) << "Can't write `" << name << '\''; } bobcat-3.19.01/errno/destructor.cc0000644000175000017500000000006012222576537015744 0ustar frankfrank#include "errno.ih" Errno::~Errno() throw() {} bobcat-3.19.01/errno/what.cc0000644000175000017500000000030212222576537014510 0ustar frankfrank/* errno.cc */ #include "errno.ih" char const *Errno::what() const throw() // required by std. exception hdr { return (d_what = d_msg + str()).c_str(); } bobcat-3.19.01/errno/open3.cc0000644000175000017500000000046612222576537014604 0ustar frankfrank#include "errno.ih" void Errno::open(std::fstream &stream, std::string const &name, ios::openmode mode) { if (stream.is_open()) stream.close(); stream.open(name.c_str(), mode); if (!stream) throw Errno(1) << "Can't open `" << name << '\''; } bobcat-3.19.01/errno/copycons.cc0000644000175000017500000000021612222576537015406 0ustar frankfrank#include "errno.ih" Errno::Errno(Errno const &other) : ostringstream(other.str()), d_errno(other.d_errno), d_msg(other.d_msg) {} bobcat-3.19.01/errno/errno.cc0000644000175000017500000000044512222576537014702 0ustar frankfrank/* errno.cc $Id$ $Log$ Revision 1.1 2005/08/19 15:12:52 frank Initial revision Revision 1.1.1.1 2003/05/28 13:32:23 frank Initial installation of FBB::Errno */ #include "errno.ih" Errno::Errno() : d_errno(errno) { initMsg(); } bobcat-3.19.01/errno/initmsg.cc0000644000175000017500000000041112222576537015220 0ustar frankfrank/* initmsg.cc */ #include "errno.ih" void Errno::initMsg() { if (d_errno) { string msg = strerror(d_errno); if (d_msg.length()) d_msg += ": " + msg; else d_msg = msg; } } bobcat-3.19.01/errno/open1.cc0000644000175000017500000000045312222576537014576 0ustar frankfrank#include "errno.ih" void Errno::open(std::ifstream &in, std::string const &name, std::ios::openmode mode) { if (in.is_open()) in.close(); in.open(name.c_str(), mode); if (!in) throw Errno(1) << "Can't read `" << name << '\''; } bobcat-3.19.01/errno/driver/0000755000175000017500000000000012222576537014536 5ustar frankfrankbobcat-3.19.01/errno/driver/build0000755000175000017500000000054712222576537015571 0ustar frankfrank#!/bin/bash tput clear GPP="g++ --std=c++0x" # CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp -lerrno -lbobcat -s" # CMD="$GPP -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib -lbobcat -s" CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp -lerrno -s" # CMD="$GPP -o driver -Wall *.cc -lbobcat -s" echo $CMD $CMD || exit 1 echo Ready... driver bobcat-3.19.01/errno/driver/driver.cc0000644000175000017500000000366212222576537016347 0ustar frankfrank#include #include "../errno" #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { string hello = "hello world"; try { try { Errno e; e << hello; throw e; } catch(Errno const &e) { cerr << e.why() << ", " << e.which() << "\n"; throw; } } catch(exception const &e) { cout << "Exception caught: " << e.why() << "\n"; } cerr << "================== second example ===============\n"; try { errno = 12; Errno e("Prefix text"); e << ".\n\tThis is the result of errno = " << errno; throw e; } catch(exception const &e) { cout << "Exception caught: " << e.why() << "\n"; } cerr << "================== third example ===============\n"; try { Errno e(12, "Prefix text"); Errno e2(e); cout << sizeof(Errno) << ' ' << sizeof(ostringstream) << ' ' << sizeof(exception) << endl; // e2 = e; e2 << ".\n\tThis is the result of 12 prefixed initialized"; throw e2; } catch(Errno const &e) { cout << "Exception caught: " << e.why() << ", " << e.which() << "\n"; } cerr << "================== fourth examplle ===============\n"; try { throw Errno(99, "Since Special") << ". Hello world " << 1234; cerr << "NOT REACHED\n"; } catch (exception const &e) { cerr << e.why() << ".\n"; } cerr << "================== fifth example ===============\n"; try { throw Errno(99, "Obsoleted") << insertable << ". Hello world " << 1234 << throwable; cerr << "NOT REACHED\n"; } catch (exception const &e) { cerr << e.why() << ".\n"; } } bobcat-3.19.01/errno/errno2.cc0000644000175000017500000000025512222576537014763 0ustar frankfrank/* errno.cc */ #include "errno.ih" Errno::Errno(char const *prefix) : d_errno(errno), d_msg(prefix ? prefix : "") { initMsg(); } bobcat-3.19.01/errno/errno3.cc0000644000175000017500000000023612222576537014763 0ustar frankfrank/* errno.cc */ #include "errno.ih" Errno::Errno(int err, char const *text) : d_errno(err), d_msg(text ? text : "") {} bobcat-3.19.01/errno/errno0000644000175000017500000000374512222576537014324 0ustar frankfrank#ifndef INCLUDED_BOBCAT_ERRNO_ #define INCLUDED_BOBCAT_ERRNO_ // errno.h is included to allow using errno values, like EINVAL #include #include #include #include #include #include namespace FBB { class Errno: public std::ostringstream, public std::exception { int d_errno; std::string d_msg; mutable std::string d_what; // throw() lists below are required by the std::exception base class public: Errno(); explicit Errno(char const *prefix); explicit Errno(int errnr, char const *text = 0); Errno(Errno const &other); virtual ~Errno() throw(); int which() const; char const *why() const; static void open(std::ifstream &in, std::string const &name, // 1 std::ios::openmode mode = std::ios::in); static void open(std::ofstream &out, std::string const &name, // 2 std::ios::openmode mode = std::ios::out); static void open(std::fstream &out, std::string const &name, // 3 std::ios::openmode mode); // moves to private in a // future release virtual char const *what() const throw(); private: void initMsg(); }; inline int Errno::which() const { return d_errno; } inline char const *Errno::why() const { return what(); } template inline Errno const &operator<<(Errno const &in, Type const &t) { dynamic_cast(const_cast(in)) << t; return in; } // OBSOLETED, NOT REQUIRED ANYMORE inline Errno &operator<<(std::ostream &str, Errno *(*)()) { return *static_cast(&(str << std::flush)); } inline std::ostream &insertable(std::ostream &errnoObject) { return errnoObject; } inline Errno *throwable() { return 0; } } // FBB #endif bobcat-3.19.01/errno/errno.ih0000644000175000017500000000030712222576537014712 0ustar frankfrank// FBB::Errno #include "errno" #include #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/exception/0000755000175000017500000000000012242431634014102 5ustar frankfrankbobcat-3.19.01/exception/errnodescr.cc0000644000175000017500000000070412222576532016565 0ustar frankfrank#include "exception.ih" namespace FBB { std::ostream &errnodescr(std::ostream &out) { if (errno != 0) { char *buffer = new char[Exception::STRERROR_BUFSIZE]; if (char *cp = strerror_r(errno, buffer, Exception::STRERROR_BUFSIZE)) out << cp; else { out << "internal error: strerror_r failed with errno = " << errno; } delete[] buffer; } return out; } } // FBB bobcat-3.19.01/exception/destructor.cc0000644000175000017500000000010312222576532016606 0ustar frankfrank#include "exception.ih" Exception::~Exception() noexcept(true) {} bobcat-3.19.01/exception/what.cc0000644000175000017500000000015312222576532015360 0ustar frankfrank#include "exception.ih" char const *Exception::what() const noexcept(true) { return d_what.c_str(); } bobcat-3.19.01/exception/exception0000644000175000017500000000340512223023055016016 0ustar frankfrank#ifndef INCLUDED_BOBCAT_EXCEPTION_ #define INCLUDED_BOBCAT_EXCEPTION_ #include #include #include #include namespace FBB { class Exception: public std::exception { template friend Exception &&operator<<(Exception &&tmp, Type const &value); std::string d_what; public: enum { STRERROR_BUFSIZE = 100 }; enum Protection { ANY, EQUAL }; Exception() = default; explicit Exception(int errnoValue); // exception1.cc ~Exception() noexcept(true) override; static size_t protection(std::string const &name, size_t protect, Protection type = EQUAL); template static void open(StreamType &stream, // open1.f std::string const &name); template static void open(int errnoValue, StreamType &stream, // open2.f std::string const &name); template static void open(StreamType &stream, // open3.f std::string const &name, std::ios::openmode mode); template static void open(int errnoValue, StreamType &stream, // open4.f std::string const &name, std::ios::openmode mode); private: char const *what() const noexcept(true) override; }; #include "open1.f" #include "open2.f" #include "open3.f" #include "open4.f" // Free functions std::ostream &errnodescr(std::ostream &out); #include "opinsert.f" // Exception << Type } // FBB #endif bobcat-3.19.01/exception/exception.ih0000644000175000017500000000032312222576532016425 0ustar frankfrank#include "exception" #include #include #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/exception/exception1.cc0000644000175000017500000000013212222576532016471 0ustar frankfrank#include "exception.ih" Exception::Exception(int errnoValue) { errno = errnoValue; } bobcat-3.19.01/exception/open1.f0000644000175000017500000000037512223023055015271 0ustar frankfranktemplate void Exception::open(StreamType &stream, std::string const &name) { if (stream.is_open()) stream.close(); stream.open(name); if (!stream) throw Exception() << "Can't open `" << name << '\''; } bobcat-3.19.01/exception/driver/0000755000175000017500000000000012222576532015402 5ustar frankfrankbobcat-3.19.01/exception/driver/build0000755000175000017500000000054412222576532016432 0ustar frankfrank#!/bin/bash tput clear GPP="g++ --std=c++0x" # CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp -lerrno -lbobcat -s" # CMD="$GPP -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib -lbobcat -s" CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp -lerrno -s" CMD="$GPP -o driver -Wall *.cc ../*.cc -s" echo $CMD $CMD || exit 1 echo Ready... driver bobcat-3.19.01/exception/driver/driver.cc0000644000175000017500000000311612222576532017205 0ustar frankfrank#include #include "../exception" #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { string hello = "hello world"; try { try { // throw exception in which data of // various types were inserted throw Exception() << hello << ' ' << 12.34 << "..."; } catch(exception const &e) { cerr << e.what() << '\n'; throw; // may be rethrown, which is standard } } catch(exception const &e) { cout << "Exception caught: " << e.what() << '\n'; } try { // throw exception in which data of // various types were inserted throw Exception(5) << "Exception with errno value set"; } catch(exception const &e) { cerr << e.what() << '\n' << "Errno == " << errno << '\n'; } try { ofstream out; Exception::open(out, "out"); Exception::open(out, ""); } catch(exception const &e) { cout << e.what() << '\n'; } try { ofstream out; Exception::open(out, "out", ios::in | ios::out); } catch(exception const &e) { cout << e.what() << '\n'; } try { throw Exception(E2BIG) << "Error: " << FBB::strerror; } catch(exception const &e) { cout << e.what() << '\n'; } } bobcat-3.19.01/exception/open4.f0000644000175000017500000000051712223023055015272 0ustar frankfranktemplate void Exception::open(int errnoValue, StreamType &stream, std::string const &name, std::ios::openmode mode) { if (stream.is_open()) stream.close(); stream.open(name, mode); if (!stream) throw Exception(errnoValue) << "Can't open `" << name << '\''; } bobcat-3.19.01/exception/opinsert.f0000644000175000017500000000030612223023055016104 0ustar frankfranktemplate inline Exception &&operator<<(Exception &&tmp, Type const &value) { std::ostringstream out; out << value; tmp.d_what += out.str(); return std::move(tmp); } bobcat-3.19.01/exception/open2.f0000644000175000017500000000045512223023055015271 0ustar frankfranktemplate void Exception::open(int errnoValue, StreamType &stream, std::string const &name) { if (stream.is_open()) stream.close(); stream.open(name); if (!stream) throw Exception(errnoValue) << "Can't open `" << name << '\''; } bobcat-3.19.01/exception/open3.f0000644000175000017500000000050512223023055015266 0ustar frankfranktemplate void Exception::open(StreamType &stream, std::string const &name, std::ios::openmode mode) { if (stream.is_open()) stream.close(); stream.open(name, mode); if (!stream) throw Exception() << "Can't open `" << name << '\''; } bobcat-3.19.01/exception/protection.cc0000644000175000017500000000210712222576532016604 0ustar frankfrank#include "exception.ih" size_t Exception::protection(std::string const &name, size_t protect, Protection type) { if (protect > 0777) throw Exception() << "Protection for `" << name << "' " "may not exceed 0777 (requested: 0" << oct << protect << dec << ')'; Stat stat(name); // does the file exist? if (not stat) // no: create it with the requested procection { // bits int fd = ::open(name.c_str(), O_CREAT, protect); if (fd < 0) throw Exception() << "Can't create 0" << oct << protect << dec << ' ' << name; close(fd); return protect; } size_t mode = stat.mode(); // get the actual mode if (type == EQUAL && mode != protect) throw Exception() << "Protection of `" << name << "' (0" << oct << mode << ") differs from required 0" << protect; return mode; } bobcat-3.19.01/fbb/0000755000175000017500000000000012222576537012647 5ustar frankfrankbobcat-3.19.01/fbb/fbb.ih0000644000175000017500000000007212222576537013721 0ustar frankfrank#include "fbb" using namespace std; using namespace FBB; bobcat-3.19.01/fbb/fbb0000644000175000017500000000022412222576537013321 0ustar frankfrank#ifndef INCLUDED_BOBCAT_FBB_ #define INCLUDED_BOBCAT_FBB_ namespace FBB { enum CryptType { DECRYPT, ENCRYPT }; } // FBB #endif bobcat-3.19.01/fnwrap/0000755000175000017500000000000012222576534013410 5ustar frankfrankbobcat-3.19.01/fnwrap/driver/0000755000175000017500000000000012222576534014703 5ustar frankfrankbobcat-3.19.01/fnwrap/driver/driver.cc0000644000175000017500000000535012222576534016510 0ustar frankfrank#include #include #include #include #include "../fnwrap" // to compile: g++ --std=c++0x driver.cc // use g++ >= 4.4 using namespace std; using namespace FBB; class Strings { vector d_vs; public: Strings() : d_vs({"one", "two", "", "three"}) {} void display(ostream &out) const { size_t nr = 0; find_if(d_vs.begin(), d_vs.end(), context(untilEmpty, nr, out)); } void display() const { for_each(d_vs.begin(), d_vs.end(), context(toCout)); } void show(ostream &out) const { size_t nr = 0; for_each(d_vs.begin(), d_vs.end(), context(all, nr, out)); } void accu(ostream &out) const { size_t nr = 0; equal(d_vs.begin(), d_vs.end(), d_vs.rbegin(), context(cmpfun2, nr, out)); } void count() { size_t nLines = 0; cout << "Number of counts: " << count_if(d_vs.begin(), d_vs.end(), context(counter, cout, nLines)); cout << '\n' << nLines << " lines processed\n"; } private: static bool cmpfun2(string const &str1, string const &str2, size_t &nr, ostream &out) { if (str1.empty()) // somewhat strange equality definition... return false; out << ++nr << ' ' << str1 << " and " << str2 << '\n'; return true; } static void toCout(string const &str) { cout << "toCout: " << str << '\n'; } static bool untilEmpty(string const &str, size_t &nr, ostream &out) { if (str.empty()) return true; // stop out << ++nr << ' ' << str << '\n'; return false; // don't stop } static void all(string const &str, size_t &nr, ostream &out) { out << ++nr << ' ' << str << '\n'; } static bool counter(string const &str, ostream &out, size_t &nLines) { out << "Line nr " << ++nLines << ": " << str; if (str.find('t') != string::npos) { out << ", contains 't'\n"; return true; } out << ", no 't'\n"; return false; } }; int main() { Strings s; s.display(cout); cout << "========\n"; s.display(); cout << "========\n"; s.show(cout); cout << "========\n"; s.accu(cout); cout << "========\n"; s.count(); } bobcat-3.19.01/fnwrap/fnwrap0000644000175000017500000001701712222576534014636 0ustar frankfrank#ifndef INCLUDED_BOBCAT_FNWRAP_ #define INCLUDED_BOBCAT_FNWRAP_ #include #include namespace FBB { class FnWrap { template struct Dissect {}; template struct Dissect { typedef Ret ReturnType; }; typedef Dissect *NotUsed; template struct At { typedef typename std::tuple_element::type Type; }; template struct CallPack: public CallPack::Type, Args ...> { typedef typename TypeTrait::Plain first_argument_type; typedef typename TypeTrait::Plain second_argument_type; typedef typename At::Type LastType; static RetType call(Func fun, Arg1 &&arg1, Arg2 &&arg2, Tuple &tuple, Args &&...args); }; // specialization: unary + ret. type template struct CallPack { static RetType call(Func fun, Arg1 &&arg1, NotUsed &&arg2, Tuple &tuple, Args &&...args); }; // specialization: binary + ret. type template struct CallPack { static RetType call(Func fun, Arg1 &&arg1, Arg2 &&arg2, Tuple &tuple, Args &&...args); }; // specialization: void unary template struct CallPack { static void call(Func fun, Arg1 &&arg1, NotUsed &&arg2, Tuple &tuple, Args &&...args); }; // specialization: void binary template struct CallPack { static void call(Func fun, Arg1 &&arg1, Arg2 &&arg2, Tuple &tuple, Args &&...args); }; public: template struct Functor { typedef typename Dissect::ReturnType RetType; Function d_function; std::tuple d_args; Functor(Function fun, Args &&... args); template typename Functor::RetType operator()(Arg1 &&arg1, Arg2 &&arg2); template typename Functor::RetType operator()(Arg1 &&arg1); }; template static Functor unary(Function fun, Args &&...args); template static Functor binary(Function fun, Args &&...args); }; // Generic CallPack::call function, unpacking the tuple template RetType FnWrap::CallPack::call(Func fun, Arg1 &&arg1, Arg2 &&arg2, Tuple &tuple, Args &&...args) { return CallPack::call(fun, std::forward(arg1), std::forward(arg2), tuple, std::forward(std::get(tuple)), std::forward(args) ... ); } // Unary void CallPack::call function template void FnWrap::CallPack::call( Func fun, Arg1 &&arg1, FnWrap::NotUsed &&arg2, Tuple &tuple, Args &&...args) { fun(std::forward(arg1), std::forward(args)...); } // Unary non-void CallPack::call function template RetType FnWrap::CallPack::call( Func fun, Arg1 &&arg1, FnWrap::NotUsed &&arg2, Tuple &tuple, Args &&...args) { return fun(std::forward(arg1), std::forward(args)...); } // Binary void CallPack::call function template void FnWrap::CallPack::call( Func fun, Arg1 &&arg1, Arg2 &&arg2, Tuple &tuple, Args &&...args) { fun(std::forward(arg1), std::forward(arg2), std::forward(args)...); } // Binary non-void CallPack::call function template RetType FnWrap::CallPack::call( Func fun, Arg1 &&arg1, Arg2 &&arg2, Tuple &tuple, Args &&...args) { return fun(std::forward(arg1), std::forward(arg1), std::forward(args)...); } // Functor's constructor template FnWrap::Functor::Functor(Function fun, Args &&... args) : d_function(fun), d_args(std::forward(args)...) {} template // unary operator() template typename FnWrap::Functor::RetType FnWrap::Functor< Function, Args...>::operator()(Arg1 &&arg1) { return CallPack >::call(d_function, std::forward(arg1), 0, d_args); } template // binary operator() template typename FnWrap::Functor::RetType FnWrap::Functor< Function, Args...>::operator()(Arg1 &&arg1, Arg2 &&arg2) { return CallPack >::call(d_function, std::forward(arg1), std::forward(arg2), d_args); } template FnWrap::Functor context(Function fun, Args &&...args) { return FnWrap::Functor (fun, std::forward(args) ...); } template FnWrap::Functor FnWrap::unary(Function fun, Args &&...args) { return Functor(fun, std::forward(args) ...); } template FnWrap::Functor FnWrap::binary(Function fun, Args &&...args) { return Functor(fun, std::forward(args) ...); } } // FBB #endif bobcat-3.19.01/foreach/0000755000175000017500000000000012222576534013522 5ustar frankfrankbobcat-3.19.01/foreach/foreach0000644000175000017500000000524612222576534015063 0ustar frankfrank#ifndef INCLUDED_BOBCAT_FOREACH_ #define INCLUDED_BOBCAT_FOREACH_ #include namespace FBB { template struct FE3 { inline void operator()(Iter begin, Iter end, Function &fun) { for ( ; begin != end; ) fun(begin++); } }; template struct FE3 { inline void operator()(Iter begin, Iter end, Function &fun) { for ( ; begin != end; ) fun(*begin++); } }; // Generic case: anything that's not specialized. // In practice: not dereferenceable, object reference template struct FE4 { inline void operator()(Iter begin, Iter end, Class &obj, Member member) { for ( ; begin != end; ) (obj.*member)(begin++); } }; // Specialization: dereferenceable, object reference template struct FE4 { inline void operator()(Iter begin, Iter end, Class &obj, Member member) { for ( ; begin != end; ) (obj.*member)(*begin++); } }; // Specialization: dereferenceable, object pointer template struct FE4 { inline void operator()(Iter begin, Iter end, Class *obj, Member member) { for ( ; begin != end; ) (obj->*member)(*begin++); } }; // Specialization: Not dereferenceable, object pointer template struct FE4 { inline void operator()(Iter begin, Iter end, Class *obj, Member member) { for ( ; begin != end; ) (obj->*member)(begin++); } }; template void for_each( Iter begin, Iter end, Function function) { FE3::isDereferenceable, Iter, Function>() (begin, end, function); } template inline void for_each(Iter begin, Iter const &end, Object &object, Member member) { FE4::isDereferenceable, Iter, Object, Member>() (begin, end, object, member); } template inline void for_each(Iter begin, Iter const &end, Object *object, Member member) { FE4::isDereferenceable, Iter, Object *, Member>() (begin, end, object, member); } } // FBB #endif bobcat-3.19.01/fork/0000755000175000017500000000000012242431634013045 5ustar frankfrankbobcat-3.19.01/fork/fork.ih0000644000175000017500000000030512222576524014334 0ustar frankfrank#include "fork" #include #include #include #include #include #include #include using namespace FBB; bobcat-3.19.01/fork/destructor.cc0000644000175000017500000000004512222576524015557 0ustar frankfrank#include "fork.ih" Fork::~Fork() {} bobcat-3.19.01/fork/fork0000644000175000017500000000133312223023055013722 0ustar frankfrank#ifndef INCLUDED_BOBCAT_FORK_ #define INCLUDED_BOBCAT_FORK_ #include namespace FBB { class Fork { pid_t d_pid; public: virtual ~Fork(); void fork(); protected: pid_t pid() const; // .f virtual void childRedirections(); // do child redirections virtual void childProcess() = 0; // must be implemented virtual void parentRedirections(); // do parent redirections virtual void parentProcess() = 0; // must be implemented void prepareDaemon() const; // prepares for a daemon int waitForChild(); // returns the status }; #include "pid.f" } // FBB #endif bobcat-3.19.01/fork/childredirections.cc0000644000175000017500000000013612222576524017060 0ustar frankfrank#include "fork.ih" void Fork::childRedirections() // do child redirections {} bobcat-3.19.01/fork/driver/0000755000175000017500000000000012222576524014346 5ustar frankfrankbobcat-3.19.01/fork/driver/build0000755000175000017500000000005412222576524015372 0ustar frankfrank#!/bin/sh g++ -o driver driver.cc -lbobcat bobcat-3.19.01/fork/driver/driver.cc0000644000175000017500000000140612222576524016151 0ustar frankfrank#include #include #include using namespace std; using namespace FBB; class Background: public Fork { public: void childProcess(); void parentProcess(); }; void Background::childProcess() { for (int idx = 0; idx < 3; ++idx) { cout << "Hello world # " << idx << endl; sleep(1); } throw 0; // caught in main() } void Background::parentProcess() { cout << "Waiting for the child process to end...\n"; cout << "The child returns value " << waitForChild() << endl; } int main() try { Background bg; bg.fork(); cout << "This is from the parent\n"; return 0; } catch(int x) { cout << "The child terminates with: " << x << endl; return x; } bobcat-3.19.01/fork/preparedaemon.cc0000644000175000017500000000103612222576524016204 0ustar frankfrank#include "fork.ih" void Fork::prepareDaemon() const { if (chdir("/") < 0) // free up mount points throw Exception() << "Fork::prepareDaemon: chdir(\"/\") failed\n"; setsid(); // create new session/process group ::close(STDIN_FILENO); // close and reopen std file descriptors ::close(STDOUT_FILENO); ::close(STDERR_FILENO); open("/dev/null", O_RDONLY); // reopen stdin open("/dev/null", O_WRONLY); // reopen cout open("/dev/null", O_WRONLY); // reopen cerr } bobcat-3.19.01/fork/forkfork.cc0000644000175000017500000000064212222576524015207 0ustar frankfrank#include "fork.ih" void Fork::fork() { if ((d_pid = ::fork()) < 0) throw Exception() << "Fork::fork(): " << errnodescr; if (d_pid == 0) // childprocess has pid == 0 { childRedirections(); childProcess(); throw Exception(1); // we shouldn't come here: childProcess should // exit } parentRedirections(); parentProcess(); } bobcat-3.19.01/fork/parentredirections.cc0000644000175000017500000000014012222576524017261 0ustar frankfrank#include "fork.ih" void Fork::parentRedirections() // do parent redirections {} bobcat-3.19.01/fork/waitforchild.cc0000644000175000017500000000020312222576524016034 0ustar frankfrank#include "fork.ih" int Fork::waitForChild() { int status; waitpid(d_pid, &status, 0); return WEXITSTATUS(status); } bobcat-3.19.01/fork/pid.f0000644000175000017500000000006512223023055013762 0ustar frankfrankinline pid_t Fork::pid() const { return d_pid; } bobcat-3.19.01/fswap/0000755000175000017500000000000012223023055013215 5ustar frankfrankbobcat-3.19.01/fswap/tswap.f0000644000175000017500000000066012223023055014524 0ustar frankfranktemplate void FSwap::tswap(Type &lhs, Type &rhs) { static_assert(sizeof(SwapType) == sizeof(Type), "BOBCAT DESIGN ERROR: " "FSwap::tswap(): sizeof(SwapType) != sizeof(Type)"); SwapType tmp = *reinterpret_cast(&lhs); *reinterpret_cast(&lhs) = *reinterpret_cast(&rhs); *reinterpret_cast(&rhs) = tmp; } bobcat-3.19.01/fswap/fswap.f0000644000175000017500000000016312223023055014504 0ustar frankfranktemplate void fswap(Type &lhs, Type &rhs) { FSwap::Xch::fswap(lhs, rhs); } bobcat-3.19.01/fswap/fswap4.f0000644000175000017500000000016012223023055014565 0ustar frankfranktemplate inline void FSwap::Xch::fswap(Tp &lhs, Tp &rhs) { tswap(lhs, rhs); } bobcat-3.19.01/fswap/fswap1.f0000644000175000017500000000033312223023055014564 0ustar frankfranktemplate void FSwap::Xch::fswap(Tp &lhs, Tp &rhs) { char buffer[size]; memcpy(buffer, &lhs, size); memcpy(&lhs, &rhs, size); memcpy(&rhs, buffer, size); } bobcat-3.19.01/fswap/driver/0000755000175000017500000000000012222576534014526 5ustar frankfrankbobcat-3.19.01/fswap/driver/build0000755000175000017500000000007012222576534015550 0ustar frankfrank#!/bin/bash g++ --std=c++0x -Wall -o driver driver.cc bobcat-3.19.01/fswap/driver/driver.cc0000644000175000017500000000110512222576534016325 0ustar frankfrank#include #include "../fswap" class Demo { std::ostream &d_out; size_t d_value; public: Demo(std::ostream &out = std::cerr, size_t value = 0) : d_out(out), d_value(value) {} void show(char const *msg) { d_out << msg << ". Value: " << d_value << '\n'; } }; using namespace std; int main() { Demo d1; Demo d2(cout, 12); FBB::fswap(d1, d2); d1.show("This is d1"); // to cerr: 12 d2.show("This is d2"); // to cout: 0 } bobcat-3.19.01/fswap/fswap0000644000175000017500000000211012223023055014252 0ustar frankfrank#ifndef INCLUDED_FSWAP_ #define INCLUDED_FSWAP_ #include #include namespace FBB { class FSwap { template struct Xch { static void fswap(Tp &lhs, Tp &rhs); // 1.f }; template struct Xch { static void fswap(Tp &lhs, Tp &rhs); // 2.f }; template struct Xch { static void fswap(Tp &lhs, Tp &rhs); // 3.f }; template struct Xch { static void fswap(Tp &lhs, Tp &rhs); // 4.f }; template struct Xch { static void fswap(Tp &lhs, Tp &rhs); // 5.f }; template static void tswap(Type &lhs, Type &rhs); // .f }; #include "tswap.f" #include "fswap1.f" #include "fswap2.f" #include "fswap3.f" #include "fswap4.f" #include "fswap5.f" // Free function #include "fswap.f" // fswap(Type &, Type & } // FBB #endif bobcat-3.19.01/fswap/fswap2.f0000644000175000017500000000015712223023055014571 0ustar frankfranktemplate inline void FSwap::Xch::fswap(Tp &lhs, Tp &rhs) { tswap(lhs, rhs); } bobcat-3.19.01/fswap/fswap3.f0000644000175000017500000000016012223023055014564 0ustar frankfranktemplate inline void FSwap::Xch::fswap(Tp &lhs, Tp &rhs) { tswap(lhs, rhs); } bobcat-3.19.01/fswap/fswap5.f0000644000175000017500000000016012223023055014566 0ustar frankfranktemplate inline void FSwap::Xch::fswap(Tp &lhs, Tp &rhs) { tswap(lhs, rhs); } bobcat-3.19.01/gethostent/0000755000175000017500000000000012242431634014270 5ustar frankfrankbobcat-3.19.01/gethostent/gethostent.ih0000644000175000017500000000035112222576535017005 0ustar frankfrank#include "gethostent" #include #include #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/gethostent/hosterror.cc0000644000175000017500000000104412222576535016635 0ustar frankfrank#include "gethostent.ih" void GetHostent::hosterror(char const *text) { string msg = text; msg += ": "; switch (h_errno) { case HOST_NOT_FOUND: msg += "Unknown host"; break; case TRY_AGAIN: msg += "Name server unreachable, try again later"; break; case NO_RECOVERY: msg += "Unrecoverable error"; break; case NO_ADDRESS: msg += "Missing address for hostname"; break; } throw Exception(h_errno) << msg; } bobcat-3.19.01/gethostent/driver/0000755000175000017500000000000012222576535015573 5ustar frankfrankbobcat-3.19.01/gethostent/driver/build0000755000175000017500000003700512222576535016625 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/driver // script generated by the C++ icmake script version 2.17b /* Configurable defines: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BISON_FLAGS: This directive is only used when a grammar is generated using bison++. It defines the set of flags that are given to bison++ when bison++ generates the parser. By default the following flags are specified: -v -l The -d and -o flags are always provided (not configurable) BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (by default it is defined to the name of the program to be created). COMPILER: The compiler to use. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) GRAMMAR_LINES: When this directive is defined, #line directives will be generated at the first C++ compound statement in each individual grammar specification file. Undefine if no such #line directives are required. LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM "driver" #define COMPILER "g++" #define COPT "-Wall" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "fbb" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current, // contains name of current dir. programname; // the name of the program to create int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); #ifdef GRAMMAR_LINES system("./grambuild lines"); #else system("./grambuild"); #endif chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { #ifdef BISON_FLAGS exec("bison++", BISON_FLAGS, "-d", "-o", "parser.cc", "grammar"); #else exec("bison++", "-d", "-o", "parser.cc", "grammar"); #endif } chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || ( exists("../parser/parser.h") && "../parser/parser.h" younger "yylex.cc" ) ) ) exec("flex", interactive, "lexer"); chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; programname = BUILD_PROGRAM; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD if (exists("parser")) // subdir parser exists { CLASSES += "parser "; parser(); } if (exists("scanner")) // subdir scanner exists { CLASSES += "scanner "; scanner(); } #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library) { printf("\n"); exec(COMPILER, "-o", programname, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", programname, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "driver.cc", // program source "driver" // static program library ); #else cpp_make ( "", "driver" // static- or so-library ); #endif } bobcat-3.19.01/gethostent/driver/driver.cc0000644000175000017500000000161212222576535017375 0ustar frankfrank/* driver.cc */ #include "driver.h" #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { if (argc == 1) { cerr << "Provide a host name or host address to solve\n"; return 1; } try { Hostent he(GetHostent::gethostent(argv[1], argv[1])); cout << "Hostname: " << he.hostname() << endl; cout << "Aliases:\n"; copy(he.beginAlias(), he.endAlias(), ostream_iterator(cout, "\n")); cout << "Addresses:\n"; for (size_t idx = 0; idx < he.nAddresses(); idx++) cout << he.dottedDecimalAddress(idx) << endl; } catch (Errno const &err) { cout << err.why() << endl; return 1; } return 0; } bobcat-3.19.01/gethostent/addresstostring.cc0000644000175000017500000000036012222576535020025 0ustar frankfrank#include "gethostent.ih" string GetHostent::addressToString(char const *prefix, void const *ads) { char buffer[100]; if (!prefix || !inet_ntop(AF_INET, ads, buffer, 100)) throw Exception() << prefix; return buffer; } bobcat-3.19.01/gethostent/gethostent0000644000175000017500000000101712222576535016406 0ustar frankfrank#ifndef INCLUDED_BOBCAT_GETHOSTENT_ #define INCLUDED_BOBCAT_GETHOSTENT_ #include struct hostent; namespace FBB { class GetHostent { public: static hostent const *gethostent(char const *errorprefix, std::string const &nameOrAddress); static std::string addressToString(char const *errorprefix, void const *ads); private: static void hosterror(char const *prefix); // throws Exception() }; } // FBB #endif bobcat-3.19.01/gethostent/gethostent.cc0000644000175000017500000000156412222576535017001 0ustar frankfrank#include "gethostent.ih" hostent const *GetHostent::gethostent(char const *prefix, string const &host) { static Pattern address("(\\d+\\.){3}\\d+"); // 4 series of . separated // digits. struct hostent *hp; try { address.match(host); // numerical address? in_addr_t adds = inet_addr(host.c_str()); // returns in_addr_t, which // is a conversion of the d.d.d.d notation // to a binary value. hp = gethostbyaddr(reinterpret_cast(&adds), sizeof(in_addr), AF_INET); } catch(...) { hp = gethostbyname(host.c_str()); } if (!hp) hosterror(prefix); // throws Exception return hp; } bobcat-3.19.01/glob/0000755000175000017500000000000012242431634013027 5ustar frankfrankbobcat-3.19.01/glob/glob1.cc0000644000175000017500000000016512222576525014353 0ustar frankfrank#include "glob.ih" Glob::Glob(string const &pattern, int flags, Dots dots) : Glob(ANY, pattern, flags, dots) {} bobcat-3.19.01/glob/begin.cc0000644000175000017500000000013312222576525014426 0ustar frankfrank#include "glob.ih" char const *const *Glob::begin() const { return d_share->begin; } bobcat-3.19.01/glob/destructor.cc0000644000175000017500000000036712222576525015551 0ustar frankfrank#include "glob.ih" Glob::~Glob() { if (!d_share) // for the move-operations return; if (!--d_share->users) { globfree(&d_share->globStruct); delete[] d_share->begin; delete d_share; } } bobcat-3.19.01/glob/glob0000644000175000017500000000327212226236641013704 0ustar frankfrank#ifndef INCLUDED_BOBCAT_GLOB_ #define INCLUDED_BOBCAT_GLOB_ #include #include #include namespace FBB { class Glob: public GS__ { struct GlobShare; GlobShare *d_share; public: enum Flags { // These flags are equal to the ones used in ERR = 1 << 0, // Return on read errors. MARK = 1 << 1, // Append a slash to each name. NOSORT = 1 << 2, // Don't sort the names. NOESCAPE = 1 << 6, // Backslashes don't quote metacharacters. PERIOD = 1 << 7, // Leading `.' can be matched by metachars. }; enum Dots { FIRST, DEFAULT }; Glob(std::string const &pattern = "*", int flags = PERIOD, // 1 Dots dots = FIRST); Glob(Type type, std::string const &pattern = "*", // 2 int flags = PERIOD, Dots dots = FIRST); Glob(Glob &&tmp); // 3 Glob(Glob const &other); // 4 ~Glob(); Glob &operator=(Glob const &other); Glob &operator=(Glob &&tmp); size_t size() const; char const *operator[](size_t idx) const; char const *const *begin() const; char const *const *end() const; void verify() const; // no-op void swap(Glob &other); private: char const **mbegin() const; // .f char const **mend() const; // .f void accept(Type type); static bool isDot(char const *cp); }; } // FBB #endif bobcat-3.19.01/glob/glob4.cc0000644000175000017500000000015112222576525014351 0ustar frankfrank#include "glob.ih" Glob::Glob(Glob const &other) { d_share = other.d_share; ++d_share->users; } bobcat-3.19.01/glob/operatorassign2.cc0000644000175000017500000000013312222576525016464 0ustar frankfrank#include "glob.ih" Glob &Glob::operator=(Glob &&tmp) { swap(tmp); return *this; } bobcat-3.19.01/glob/accept.cc0000644000175000017500000000116012222576525014602 0ustar frankfrank#include "glob.ih" void Glob::accept(Type type) { auto begin = d_share->begin = new char *[d_share->globStruct.gl_pathc]; auto dest = begin; for ( auto src = d_share->globStruct.gl_pathv, end = src + d_share->globStruct.gl_pathc; src != end; ++src ) { if (Stat(*src).type() & type) *dest++ = *src; // copy the pointer if type is OK } d_share->size = dest - begin; // compute the # of accepted entries d_share->end = dest; // end points beyond the last one } bobcat-3.19.01/glob/driver/0000755000175000017500000000000012222576525014331 5ustar frankfrankbobcat-3.19.01/glob/driver/build0000755000175000017500000000055512222576525015363 0ustar frankfrank#!/bin/bash tput clear GPP="g++ --std=c++0x" CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp -lglob -lbobcat -s" # CMD="$GPP -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib -lbobcat -s" # CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp -lglob -lbobcat -s" # CMD="$GPP -o driver -Wall *.cc -lbobcat -s" echo $CMD $CMD || exit 1 echo Ready... driver bobcat-3.19.01/glob/driver/driver.cc0000644000175000017500000000267412222576525016144 0ustar frankfrank/* driver.cc */ #include #include #include #include "../glob" using namespace std; using namespace FBB; Glob makeGlob(char const *pat) { cout << "Using pattern " << pat << '\n'; return Glob(pat, Glob::PERIOD, Glob::DEFAULT); } int main(int argc, char **argv) try { if (argc == 1) { cout << "Provide glob-expression as 1st arg\n"; return 1; } cout << "\nGeneral:\n"; Glob general; for (size_t idx = 0; idx < general.size(); idx++) cout << idx << ": " << general[idx] << '\n'; cout << "\nPattern: " << argv[1] << "\n"; Glob pattern(makeGlob(argv[1])); Glob copy(pattern); copy = general; for (size_t idx = 0; idx < pattern.size(); idx++) cout << idx << ": " << pattern[idx] << '\n'; pattern = Glob(Glob::DIRECTORY, argv[1], Glob::PERIOD, Glob::FIRST); cout << "Only directories:\n"; for (size_t idx = 0; idx < pattern.size(); idx++) cout << idx << ": " << pattern[idx] << '\n'; pattern = Glob(Glob::REGULAR_FILE, argv[1], Glob::PERIOD, Glob::FIRST); cout << "regular files:\n"; for (size_t idx = 0; idx < pattern.size(); idx++) cout << idx << ": " << pattern[idx] << '\n'; cout << "\nThe next glob fails, this is intentional\n"; Glob fails("*", 1023); return 0; } catch (Errno const &err) { cout << err.why() << '\n'; return err.which(); } bobcat-3.19.01/glob/glob.ih0000644000175000017500000000060312226236616014300 0ustar frankfrank#include "glob" #include #include #include #include #include using namespace std; using namespace FBB; struct Glob::GlobShare { glob_t globStruct; size_t users; size_t gsType; char **begin; char **end; size_t size; }; #include "mbegin.f" #include "mend.f" bobcat-3.19.01/glob/end.cc0000644000175000017500000000012712222576525014113 0ustar frankfrank#include "glob.ih" char const *const *Glob::end() const { return d_share->end; } bobcat-3.19.01/glob/verify.cc0000644000175000017500000000006112222576525014646 0ustar frankfrank#include "glob.ih" void Glob::verify() const {} bobcat-3.19.01/glob/glob3.cc0000644000175000017500000000013712222576525014354 0ustar frankfrank#include "glob.ih" Glob::Glob(Glob &&tmp) : d_share(tmp.d_share) { tmp.d_share = 0; } bobcat-3.19.01/glob/operatorindex.cc0000644000175000017500000000017412222576525016232 0ustar frankfrank#include "glob.ih" char const *Glob::operator[](size_t idx) const { return idx < size() ? d_share->begin[idx] : ""; } bobcat-3.19.01/glob/glob2.cc0000644000175000017500000000104712222576525014354 0ustar frankfrank#include "glob.ih" Glob::Glob(Type type, string const &pattern, int flags, Dots dots) try : d_share(new GlobShare {glob_t {}, 1, type} ) { if (flags & ~(ERR | MARK | NOSORT | NOESCAPE | PERIOD)) throw Exception(flags) << "Glob: unknown Flag specified"; int err = glob(pattern.c_str(), flags, 0, &d_share->globStruct); if (err) throw Exception(err) << "Glob: glob() failed"; accept(type); if (dots == FIRST) stable_partition(mbegin(), mend(), isDot); } catch(...) { delete d_share; throw; } bobcat-3.19.01/glob/isdot.cc0000644000175000017500000000025512222576525014471 0ustar frankfrank#include "glob.ih" namespace { string const dot("."); string const dot2(".."); } bool Glob::isDot(char const *cp) { return dot == cp || dot2 == cp; } bobcat-3.19.01/glob/mbegin.f0000644000175000017500000000014312223023055014426 0ustar frankfrankinline char const **Glob::mbegin() const { return const_cast(d_share->begin); } bobcat-3.19.01/glob/swap.cc0000644000175000017500000000011712222576525014316 0ustar frankfrank#include "glob.ih" void Glob::swap(Glob &other) { fswap(*this, other); } bobcat-3.19.01/glob/mend.f0000644000175000017500000000013712223023055014113 0ustar frankfrankinline char const **Glob::mend() const { return const_cast(d_share->end); } bobcat-3.19.01/glob/size.cc0000644000175000017500000000011512222576525014314 0ustar frankfrank#include "glob.ih" size_t Glob::size() const { return d_share->size; } bobcat-3.19.01/glob/operatorassign.cc0000644000175000017500000000016712222576525016411 0ustar frankfrank#include "glob.ih" Glob &Glob::operator=(Glob const &other) { Glob tmp(other); swap(tmp); return *this; } bobcat-3.19.01/gs/0000755000175000017500000000000012223023055012506 5ustar frankfrankbobcat-3.19.01/gs/opbinor.f0000644000175000017500000000027112223023055014325 0ustar frankfrankinline GS__::Type operator|(GS__::Type lhs, GS__::Type rhs) { return static_cast( static_cast(lhs) | static_cast(rhs) ); } bobcat-3.19.01/gs/gs0000644000175000017500000000130412223023055013040 0ustar frankfrank#ifndef INCLUDED_GS_ #define INCLUDED_GS_ namespace FBB { struct GS__ { enum Type { BLOCK_DEVICE = 0060000, CHARACTER_DEVICE = 0020000, DIRECTORY = 0040000, FIFO = 0010000, REGULAR_FILE = 0100000, SOCKET = 0140000, SYMBOLIC_LINK = 0120000, ANY = BLOCK_DEVICE | CHARACTER_DEVICE | DIRECTORY | FIFO | REGULAR_FILE | SOCKET | SYMBOLIC_LINK }; }; #include "opbinor.f" // Type | Type } // namespace FBB #endif bobcat-3.19.01/hash/0000755000175000017500000000000012223023055013020 5ustar frankfrankbobcat-3.19.01/hash/hashcharptr1.f0000644000175000017500000000016612223023055015562 0ustar frankfranktemplate inline HashCharPtr::HashCharPtr(HashCharPtr &&tmp) : BaseClass(std::move(tmp)) {} bobcat-3.19.01/hash/opfun3.f0000644000175000017500000000026212223023055014401 0ustar frankfrankinline bool CaseEqual::operator()(std::string const &s1, std::string const &s2) const { return FBB::String::casecmp(s1, s2) == 0; } bobcat-3.19.01/hash/hashcharcaseptr3.f0000644000175000017500000000034712223023055016421 0ustar frankfranktemplate template inline HashCharCasePtr::HashCharCasePtr(InputIterator first, InputIterator beyond) : BaseClass(first, beyond) {} bobcat-3.19.01/hash/hashstringcase2.f0000644000175000017500000000032212223023055016254 0ustar frankfranktemplate inline HashStringCase::HashStringCase(std::initializer_list iniValues) : BaseClass(iniValues) {} bobcat-3.19.01/hash/hashstring3.f0000644000175000017500000000032312223023055015422 0ustar frankfranktemplate template inline HashString::HashString(InputIterator first, InputIterator beyond) : BaseClass(first, beyond) {} bobcat-3.19.01/hash/hashstringcase3.f0000644000175000017500000000034312223023055016260 0ustar frankfranktemplate template inline HashStringCase::HashStringCase(InputIterator first, InputIterator beyond) : BaseClass(first, beyond) {} bobcat-3.19.01/hash/hashstring4.f0000644000175000017500000000025612223023055015430 0ustar frankfranktemplate inline HashString &HashString::operator=(HashString &&tmp) { static_cast(*this) = std::move(tmp); return *this; } bobcat-3.19.01/hash/hashcharcaseptr4.f0000644000175000017500000000035612223023055016422 0ustar frankfranktemplate inline HashCharCasePtr &HashCharCasePtr::operator=( HashCharCasePtr &&tmp) { static_cast(*this) = std::move(tmp); return *this; } bobcat-3.19.01/hash/driver/0000755000175000017500000000000012222576537014334 5ustar frankfrankbobcat-3.19.01/hash/driver/driver.cc0000644000175000017500000000070112222576537016134 0ustar frankfrank#include "../hash" #include using namespace FBB; using namespace std; int main(int argc, char **argv) { HashStringCase hsc; hsc["AAP"] = "noot"; hsc["Aap"] = "mies"; cout << hsc["aap"] << endl; HashString hs; hs["AAP"] = "noot"; hs["Aap"] = "mies"; cout << hs["AAP"] << endl; HashCharPtr hcp; hcp["jan"] = 31; hcp["feb"] = 28; cout << hcp["jan"] << endl; } bobcat-3.19.01/hash/driver/driver2.cc0000644000175000017500000000151312222576537016220 0ustar frankfrank// With g++ 4.3 ext/hash_map is deprecated. The following example shows how to // use hashes with version >= 4.3: // FOR NOW, THE OPTION -std=c++0x IS REQUIRED #include #include #include using namespace std; class Hash { public: size_t operator()(char const *str) const { size_t ret = 0; for (size_t idx = 0; *str; ++idx, ++str) ret += idx + *str; return ret; } }; int main(int argc, char *const *const argv) { pair d[] = { pair("aap", 18), pair("noot", 20), pair("wim", 30) }; unordered_map> hcp(d, d + 3); cout << hcp["noot"] << endl; return 0; } bobcat-3.19.01/hash/hashcharcaseptr1.f0000644000175000017500000000020212223023055016405 0ustar frankfranktemplate inline HashCharCasePtr::HashCharCasePtr(HashCharCasePtr &&tmp) : BaseClass(std::move(tmp)) {} bobcat-3.19.01/hash/opfun2.f0000644000175000017500000000016112223023055014376 0ustar frankfrankinline bool CaseEqual::operator()(char const *s1, char const *s2) const { return strcasecmp(s1, s2) == 0; } bobcat-3.19.01/hash/hashstring1.f0000644000175000017500000000016412223023055015423 0ustar frankfranktemplate inline HashString::HashString(HashString &&tmp) : BaseClass(std::move(tmp)) {} bobcat-3.19.01/hash/hashstring2.f0000644000175000017500000000031212223023055015417 0ustar frankfranktemplate inline HashString::HashString(std::initializer_list iniValues) : BaseClass(iniValues) {} bobcat-3.19.01/hash/opfun4.f0000644000175000017500000000016012223023055014377 0ustar frankfrankinline bool CharPtrEqual::operator()(char const *s1, char const *s2) const { return strcmp(s1, s2) == 0; } bobcat-3.19.01/hash/hash0000644000175000017500000001127312223023055013672 0ustar frankfrank#ifndef INCLUDED_BOBCAT_HASH_ #define INCLUDED_BOBCAT_HASH_ #include #include #include #include namespace FBB { // Support structs // =============== struct CaseHash { size_t operator()(std::string const &key) const; // opfun1.f }; struct CaseEqual { bool operator()(char const *s1, char const *s2) const; // opfun2.f bool operator()(std::string const &s1, // opfun3.f std::string const &s2) const; }; struct CharPtrEqual { bool operator()(char const *s1, char const *s2) const; // opfun4.f }; // HashCharPtr: case sensitive char const *keys // ============================================ template class HashCharPtr: public std::unordered_map< char const *, Value, std::hash, CharPtrEqual > { typedef std::unordered_map< char const *, Value, std::hash, CharPtrEqual > BaseClass; public: typedef typename BaseClass::value_type value_type; HashCharPtr() = default; HashCharPtr(HashCharPtr &&tmp); // 1.f HashCharPtr(std::initializer_list iniValues); // 2.f template HashCharPtr(InputIterator first, InputIterator beyond); // 3.f HashCharPtr &operator=(HashCharPtr &&tmp); // 4.f }; // HashCharCasePtr: case insensitive char const *keys // ================================================== template class HashCharCasePtr: public std::unordered_map< char const *, Value, CaseHash, CaseEqual > { typedef std::unordered_map BaseClass; public: typedef typename BaseClass::value_type value_type; HashCharCasePtr() = default; HashCharCasePtr(HashCharCasePtr &&tmp); // 1.f HashCharCasePtr(std::initializer_list iniValues); // 2.f template HashCharCasePtr(InputIterator first, InputIterator beyond); // 3.f HashCharCasePtr &operator=(HashCharCasePtr &&tmp); // 4.f }; // HashString: case sensitive std::string keys // =========================================== template class HashString: public std::unordered_map { typedef std::unordered_map BaseClass; public: typedef typename BaseClass::value_type value_type; HashString() = default; HashString(HashString &&tmp); // 1.f HashString(std::initializer_list iniValues); // 2.f template HashString(InputIterator first, InputIterator beyond); // 3.f HashString &operator=(HashString &&tmp); // 4.f }; // HashStringCase: case insensitive std::string keys // ================================================= template class HashStringCase: public std::unordered_map< std::string, Value, CaseHash, CaseEqual > { typedef std::unordered_map BaseClass; public: typedef typename BaseClass::value_type value_type; HashStringCase() = default; HashStringCase(HashStringCase &&tmp); // 1.f HashStringCase(std::initializer_list iniValues); // 2.f template HashStringCase(InputIterator first, InputIterator beyond); // 3.f HashStringCase &operator=(HashStringCase &&tmp); // 4.f }; #include "opfun1.f" #include "opfun2.f" #include "opfun3.f" #include "opfun4.f" #include "hashcharptr1.f" #include "hashcharptr2.f" #include "hashcharptr3.f" #include "hashcharptr4.f" #include "hashcharcaseptr1.f" #include "hashcharcaseptr2.f" #include "hashcharcaseptr3.f" #include "hashcharcaseptr4.f" #include "hashstring1.f" #include "hashstring2.f" #include "hashstring3.f" #include "hashstring4.f" #include "hashstringcase1.f" #include "hashstringcase2.f" #include "hashstringcase3.f" #include "hashstringcase4.f" } // FBB #endif bobcat-3.19.01/hash/hashstringcase1.f0000644000175000017500000000020012223023055016246 0ustar frankfranktemplate inline HashStringCase::HashStringCase(HashStringCase &&tmp) : BaseClass(std::move(tmp)) {} bobcat-3.19.01/hash/hashstringcase4.f0000644000175000017500000000035312223023055016262 0ustar frankfranktemplate inline HashStringCase &HashStringCase::operator=( HashStringCase &&tmp) { static_cast(*this) = std::move(tmp); return *this; } bobcat-3.19.01/hash/hashcharptr4.f0000644000175000017500000000026112223023055015561 0ustar frankfranktemplate inline HashCharPtr &HashCharPtr::operator=(HashCharPtr &&tmp) { static_cast(*this) = std::move(tmp); return *this; } bobcat-3.19.01/hash/hashcharptr3.f0000644000175000017500000000033712223023055015564 0ustar frankfranktemplate template inline HashCharPtr::HashCharPtr(InputIterator first, InputIterator beyond) : BaseClass(first, beyond) {} bobcat-3.19.01/hash/hashcharptr2.f0000644000175000017500000000031412223023055015556 0ustar frankfranktemplate inline HashCharPtr::HashCharPtr(std::initializer_list iniValues) : BaseClass(iniValues) {} bobcat-3.19.01/hash/opfun1.f0000644000175000017500000000020012223023055014367 0ustar frankfrankinline size_t CaseHash::operator()(std::string const &key) const { return std::hash()(FBB::String::lc(key)); } bobcat-3.19.01/hash/hashcharcaseptr2.f0000644000175000017500000000026412223023055016416 0ustar frankfranktemplate inline HashCharCasePtr::HashCharCasePtr( std::initializer_list iniValues) : BaseClass(iniValues) {} bobcat-3.19.01/hmacbuf/0000755000175000017500000000000012257325714013520 5ustar frankfrankbobcat-3.19.01/hmacbuf/destructor.cc0000644000175000017500000000010312222576527016221 0ustar frankfrank#include "hmacbuf.ih" HMacBuf::~HMacBuf() { delete d_pimpl; } bobcat-3.19.01/hmacbuf/operatorinsert.cc0000644000175000017500000000045012222576527017110 0ustar frankfrank#include "hmacbuf.ih" namespace FBB { std::ostream &operator<<(std::ostream &out, HMacBuf const &digestbuf) { OHexStreambuf ohex(out); ostream outs(&ohex); outs.write(digestbuf.d_pimpl->digest.data(), digestbuf.d_pimpl->digest.length()); return out; } } // FBB bobcat-3.19.01/hmacbuf/hmacbuf0000644000175000017500000000126612222576527015057 0ustar frankfrank#ifndef INCLUDED_HMACBUF_ #define INCLUDED_HMACBUF_ #include #include namespace FBB { struct HMacBufImp; class HMacBuf: public std::streambuf { friend std::ostream &operator<<(std::ostream &out, HMacBuf const &hmacbuf); HMacBufImp *d_pimpl; public: HMacBuf(std::string const &key, char const *type, size_t bufsize = 1024); virtual ~HMacBuf(); void open(); void close(); std::string const &hash() const; private: virtual int overflow(int c); }; std::ostream &operator<<(std::ostream &out, HMacBuf const &hmacbuf); } // FBB #endif bobcat-3.19.01/hmacbuf/destructor.f0000644000175000017500000000007312223023055016047 0ustar frankfrankinline HMacBufImp::~HMacBufImp() { delete [] buffer; } bobcat-3.19.01/hmacbuf/open.cc0000644000175000017500000000044012222576527014770 0ustar frankfrank#include "hmacbuf.ih" void HMacBuf::open() { d_pimpl->ctx = HMAC_CTX(); HMAC_CTX_init(&d_pimpl->ctx); HMAC_Init_ex(&d_pimpl->ctx, d_pimpl->key.c_str(), d_pimpl->key.length(), d_pimpl->md, 0); setp(d_pimpl->buffer, d_pimpl->buffer + d_pimpl->bufsize); } bobcat-3.19.01/hmacbuf/hmacbuf.ih0000644000175000017500000000104512223023055015431 0ustar frankfrank#include "hmacbuf" #include #include #include #include #include "../ohexstreambuf/ohexstreambuf" namespace FBB { struct HMacBufImp { HMAC_CTX ctx; EVP_MD const *md; std::string digest; char *buffer; size_t bufsize; std::string key; HMacBufImp(std::string const &key, size_t bufsize); ~HMacBufImp(); // destructor.i }; #include "destructor.f" } // FBB using namespace std; using namespace FBB; bobcat-3.19.01/hmacbuf/hash.cc0000644000175000017500000000013312222576527014751 0ustar frankfrank#include "hmacbuf.ih" string const &HMacBuf::hash() const { return d_pimpl->digest; } bobcat-3.19.01/hmacbuf/driver/0000755000175000017500000000000012222576530015007 5ustar frankfrankbobcat-3.19.01/hmacbuf/driver/build0000755000175000017500000000045412222576530016037 0ustar frankfrank#!/bin/sh # ln -s .. bobcat # # g++ -I. --std=c++0x -O2 -Wall -o driver driver.cc -lssl -lbobcat \ # -L../../ohexstreambuf/tmp -L../tmp -lhmacbuf -lohexstreambuf # # rm bobcat tput clear LIBS=" -lbobcat" GPP="g++ --std=c++0x" CMD="$GPP -o driver -Wall *.cc ${LIBS} -s" echo ${CMD} ${CMD} bobcat-3.19.01/hmacbuf/driver/driver.cc0000644000175000017500000000127012222576530016611 0ustar frankfrank#include #include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc < 3) throw Errno(1, "Arg1: key, arg2: digest method required"); string key(argv[1]); HMacBuf hmacbuf(key, argv[2]); ostream out(&hmacbuf); string hw("hello world\n"); out << hw; hmacbuf.close(); cout << ">" << hmacbuf << "<" << endl; hmacbuf.open(); out.write(hw.c_str(), hw.length()); hmacbuf.close(); cout << ">" << hmacbuf << "<" << endl; } catch(Errno const &err) { cout << err.why() << endl; return 1; } bobcat-3.19.01/hmacbuf/hmacbuf1.cc0000644000175000017500000000112312222576530015506 0ustar frankfrank#include "hmacbuf.ih" HMacBuf::HMacBuf(std::string const &key, char const *type, size_t bufsize) : d_pimpl(new HMacBufImp(key, bufsize)) { try { OpenSSL_add_all_digests(); d_pimpl->md = EVP_get_digestbyname(type); if (!d_pimpl->md) { if (type == 0) type = "** unspecified hmac-digest type **"; throw Exception(1) << "HMacBuf `" << type << "' not available"; } d_pimpl->buffer = new char[bufsize]; open(); } catch (...) { delete d_pimpl; throw; } } bobcat-3.19.01/hmacbuf/overflow.cc0000644000175000017500000000054212222576530015667 0ustar frankfrank#include "hmacbuf.ih" int HMacBuf::overflow(int c) { HMAC_Update(&d_pimpl->ctx, reinterpret_cast(d_pimpl->buffer), d_pimpl->bufsize); setp(d_pimpl->buffer, d_pimpl->buffer + d_pimpl->bufsize); if (c != EOF) { *pptr() = static_cast(c); pbump(1); } return c; } bobcat-3.19.01/hmacbuf/hmacbufimp1.cc0000644000175000017500000000021512222576530016215 0ustar frankfrank#include "hmacbuf.ih" HMacBufImp::HMacBufImp(std::string const &key, size_t bufsize) : buffer(0), bufsize(bufsize), key(key) {} bobcat-3.19.01/hmacbuf/close.cc0000644000175000017500000000102312222576530015124 0ustar frankfrank#include "hmacbuf.ih" void HMacBuf::close() { char *digestbuf = new char[EVP_MAX_MD_SIZE]; if (pptr() > pbase()) HMAC_Update(&d_pimpl->ctx, reinterpret_cast(d_pimpl->buffer), pptr() - pbase()); unsigned int digestbufLen; HMAC_Final(&d_pimpl->ctx, reinterpret_cast(digestbuf), &digestbufLen); d_pimpl->digest.assign(digestbuf, digestbufLen); HMAC_cleanup(&d_pimpl->ctx); delete[] digestbuf; } bobcat-3.19.01/hostent/0000755000175000017500000000000012242431634013570 5ustar frankfrankbobcat-3.19.01/hostent/dotteddecimaladdress.cc0000644000175000017500000000035212222576537020261 0ustar frankfrank#include "hostent.ih" string Hostent::dottedDecimalAddress(size_t nr) const { char buffer[100]; char const *ba = binaryAddress(nr); return (ba && inet_ntop(AF_INET, ba, buffer, 100)) ? buffer : ""; } bobcat-3.19.01/hostent/destroy.cc0000644000175000017500000000053112222576537015601 0ustar frankfrank#include "hostent.ih" void Hostent::destroy() { if (h_name == 0) return; delete h_name; if (h_aliases) { for (char **ptr = h_aliases; *ptr; ++ptr) // delete aliases entries delete *ptr; delete [] h_aliases; // and the array itself. } delete h_addr_list; } bobcat-3.19.01/hostent/hostent1.cc0000644000175000017500000000026512222576537015661 0ustar frankfrank#include "hostent.ih" Hostent::Hostent() : d_nAliases(0), d_nAddresses(0) { h_name = 0; h_aliases = 0; h_addrtype = 0; h_length = 0; h_addr_list = 0; } bobcat-3.19.01/hostent/countaliases.cc0000644000175000017500000000030012222576537016574 0ustar frankfrank#include "hostent.ih" size_t Hostent::countAliases(char const * const *alias) const { size_t idx = 1; // counts the final 0-ptr. while (*alias++) idx++; return idx; } bobcat-3.19.01/hostent/addresslength.f0000644000175000017500000000010612223023055016554 0ustar frankfrankinline size_t Hostent::addressLength() const { return h_length; } bobcat-3.19.01/hostent/hostent2.cc0000644000175000017500000000022612222576537015657 0ustar frankfrank#include "hostent.ih" Hostent::Hostent(Hostent &&tmp) { swap(tmp); tmp.h_name = 0; // prevent tmp's ~Hostent from deleting wild pointers } bobcat-3.19.01/hostent/endalias.f0000644000175000017500000000013412223023055015506 0ustar frankfrankinline char const * const *Hostent::endAlias() const { return h_aliases + nAliases(); } bobcat-3.19.01/hostent/naliases.f0000644000175000017500000000010712223023055015525 0ustar frankfrankinline size_t Hostent::nAliases() const { return d_nAliases - 1; } bobcat-3.19.01/hostent/alias.f0000644000175000017500000000015012223023055015015 0ustar frankfrankinline char const *Hostent::alias(size_t nr) const { return nr >= d_nAliases ? 0 : h_aliases[nr]; } bobcat-3.19.01/hostent/addresstype.f0000644000175000017500000000010612223023055016254 0ustar frankfrankinline size_t Hostent::addressType() const { return h_addrtype; } bobcat-3.19.01/hostent/destructor.f0000644000175000017500000000005712223023055016130 0ustar frankfrankinline Hostent::~Hostent() { destroy(); } bobcat-3.19.01/hostent/hostent1.f0000644000175000017500000000015212223023055015473 0ustar frankfrankinline Hostent::Hostent(Hostent const &other) { copy(&other, other.d_nAliases, other.d_nAddresses); } bobcat-3.19.01/hostent/xstrdup.cc0000644000175000017500000000025012222576537015617 0ustar frankfrank#include "hostent.ih" char *Hostent::xstrdup(char const *src) { return src ? strcpy(new char[1 + strlen(src)], src) : 0; } bobcat-3.19.01/hostent/copy.cc0000644000175000017500000000117412222576537015066 0ustar frankfrank#include "hostent.ih" void Hostent::copy(hostent const *other, size_t n_aliases, size_t n_addresses) { d_nAliases = n_aliases; d_nAddresses = n_addresses; h_addrtype = other->h_addrtype; h_length = other->h_length; h_name = xstrdup(other->h_name); h_aliases = new char *[d_nAliases]; for (size_t idx = 0; idx < n_aliases; idx++) h_aliases[idx] = xstrdup(other->h_aliases[idx]); h_addr_list = reinterpret_cast( memcpy(new char [n_addresses * h_length], other->h_addr_list, n_addresses * h_length)); } bobcat-3.19.01/hostent/naddresses.f0000644000175000017500000000011312223023055016056 0ustar frankfrankinline size_t Hostent::nAddresses() const { return d_nAddresses - 1; } bobcat-3.19.01/hostent/driver/0000755000175000017500000000000012222576537015075 5ustar frankfrankbobcat-3.19.01/hostent/driver/build0000755000175000017500000000044712222576537016127 0ustar frankfrank#!/bin/bash tput clear GPP="g++ --std=c++0x" CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp -lhostent -lbobcat -s" # CMD="$GPP -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib -lbobcat -s" # CMD="$GPP -o driver -Wall *.cc -lbobcat -s" echo $CMD $CMD || exit 1 echo Ready... driver bobcat-3.19.01/hostent/driver/driver.cc0000644000175000017500000000132312222576537016676 0ustar frankfrank/* driver.cc */ #include "../hostent" #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { Hostent he(gethostbyname("localhost")); { Hostent he2(he); cout << "The local hostname = " << he2.hostname() << endl; cout << "All aliases: " << endl; copy(he2.beginAlias(), he2.endAlias(), ostream_iterator(cout, "\n")); cout << "Addresses:\n"; for (size_t idx = 0; idx < he2.nAddresses(); idx++) cout << he2.dottedDecimalAddress(idx) << endl; cout << "he2 destroyed\n"; } return 0; } bobcat-3.19.01/hostent/countaddresses.cc0000644000175000017500000000063712222576537017145 0ustar frankfrank#include "hostent.ih" size_t Hostent::countAddresses(char const * const *addresses, size_t length) const { PTR p = {addresses}; size_t n = 1; // counts the final 0-address while ( static_cast(count(p.p1, p.p1 + length, char())) != length ) { p.p1 += length; n++; } return n; } bobcat-3.19.01/hostent/opis.f0000644000175000017500000000012712223023055014702 0ustar frankfrankinline Hostent &Hostent::operator=(Hostent &&tmp) { swap(tmp); return *this; } bobcat-3.19.01/hostent/beginalias.f0000644000175000017500000000012112223023055016020 0ustar frankfrankinline char const * const *Hostent::beginAlias() const { return h_aliases; } bobcat-3.19.01/hostent/hostname.f0000644000175000017500000000010412223023055015541 0ustar frankfrankinline char const *Hostent::hostname() const { return h_name; } bobcat-3.19.01/hostent/swap.cc0000644000175000017500000000013012222576537015055 0ustar frankfrank#include "hostent.ih" void Hostent::swap(Hostent &other) { fswap(*this, other); } bobcat-3.19.01/hostent/hostent0000644000175000017500000000426712223023055015201 0ustar frankfrank#ifndef INCLUDED_BOBCAT_HOSTENT_ #define INCLUDED_BOBCAT_HOSTENT_ #include #include namespace FBB { class Hostent: private hostent { union PTR { char const * const *p2; char const *p1; }; size_t d_nAliases; size_t d_nAddresses; public: Hostent(); Hostent(Hostent const &other); // hostent1.f Hostent(Hostent &&tmp); explicit Hostent(hostent const *other); ~Hostent(); // destructor.f Hostent &operator=(Hostent const &other); Hostent &operator=(Hostent &&tmp); // opis.f char const *alias(size_t nr) const; // .f char const *binaryAddress(size_t nr) const; // .f length bytes! char const * const *beginAlias() const; // .f std::string dottedDecimalAddress(size_t nr) const; char const * const *endAlias() const; // .f char const *hostname() const; // .f size_t nAliases() const; // .f size_t nAddresses() const; // .f size_t addressLength() const; // .f size_t addressType() const; // .f void swap(Hostent &other); private: static char *xstrdup(char const *src); void copy(hostent const *other, size_t n_aliases, size_t n_addresses); void destroy(); // the count functions also count // the final 0-values. size_t countAliases(char const * const *alias) const; size_t countAddresses(char const * const *addresses, size_t length) const; }; #include "addresslength.f" #include "addresstype.f" #include "alias.f" #include "beginalias.f" #include "binaryaddress.f" #include "destructor.f" #include "endalias.f" #include "hostent1.f" #include "hostname.f" #include "naddresses.f" #include "naliases.f" #include "opis.f" } // FBB #endif bobcat-3.19.01/hostent/binaryaddress.f0000644000175000017500000000016412223023055016563 0ustar frankfrankinline char const *Hostent::binaryAddress(size_t nr) const { return nr >= nAddresses() ? 0 : h_addr_list[nr]; } bobcat-3.19.01/hostent/operatorassign.cc0000644000175000017500000000020612222576537017147 0ustar frankfrank#include "hostent.ih" Hostent &Hostent::operator=(Hostent const &other) { Hostent tmp(other); swap(tmp); return *this; } bobcat-3.19.01/hostent/hostent3.cc0000644000175000017500000000027112222576537015660 0ustar frankfrank#include "hostent.ih" Hostent::Hostent(hostent const *other) { copy(other, countAliases(other->h_aliases), countAddresses(other->h_addr_list, other->h_length)); } bobcat-3.19.01/hostent/hostent.ih0000644000175000017500000000030712222576537015610 0ustar frankfrank#include "hostent" #include #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/hostname/0000755000175000017500000000000012242431634013722 5ustar frankfrankbobcat-3.19.01/hostname/hostname.ih0000644000175000017500000000025512222576524016072 0ustar frankfrank#include "hostname" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/hostname/hostname0000644000175000017500000000072312226263347015473 0ustar frankfrank#ifndef INCLUDED_BOBCAT_HOSTNAME_ #define INCLUDED_BOBCAT_HOSTNAME_ #include namespace FBB { class InetAddress; class Hostname: public Hostent { public: Hostname() = default; // may be name or dotted decimal address explicit Hostname(std::string const &host); // 1 explicit Hostname(InetAddress const &address); // 2 private: void init(); }; } // FBB #endif bobcat-3.19.01/hostname/build0000755000175000017500000004302512223023055014744 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/hostname // script generated by the C++ icmake script version 2.02 /* Configurable defines for the build script: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.fm BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. When defined as an EMPTY STRING, the static library libXXX.a is created: all programs linked to this library will themselves contain the code of the required object modules. This will result in code duplication over different programs linked to this library. When defined as a VERSION STRING, e.g., 1.0.4, a shared library libXXX.so.VERSION is constructed, as well as the links libXXX.so.MAINVERSION and libXXX.so (e.g. 1.0.0 creates libXXX.so.1.0.0, libXXX.so.1 and libXXX.so). Note that with a shared library, the library is always constructed fresh from the compiled object files. But programs linked to this library will SHARE the code stored in the shared library. These programs will therefore tend to be relatively small. Also note that `ldconfig -v' might be required after installing a shared library (libXXX.so) for the first time, so that the linker knows of its existence (in ld.so.cache) BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (default: defined). COMPILER: The compiler to use. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking LOCAL_NAMESPACE:The namespace that you, the programmer, use yourself. USING: List of :-separated namespaces to be used in sources and .fh files, appearing in `using' directives. USING does NOT automatically include LOCAL_NAMESPACE: add your LOCAL_NAMESPACE name to this list if want a `using' directive for your own namespace as well. Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.fm RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY "" #define BUILD_PROGRAM #define COMPILER "g++-3.2" #define COPT "-Wall -fsize_t-char" #define ECHO_REQUEST 1 //#define GDB "-g" #define ICMAKE "/usr/bin/icmake" #define LIBS "" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path libso, // symbolic link to so.major library path libsomajor, // lib.so.major path ofiles, // wildcards for o-files sources, // sources to be used current; // contains name of current dir. int nClasses, // number of classes/subdirectories program, // 1: program is built so_lib; // 1: so_lib is built list classes; // list of classes/directories /* parser.fm */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", interactive, "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; so_lib = 0; #else program = 0; #endif; #ifdef BUILD_LIBRARY if (strlen(BUILD_LIBRARY)) so_lib = !program; else so_lib = 0; #else if (!program) { printf("no program, no library ?\n"); exit(1); } #endif if (so_lib) copt += " -fPIC"; cwd = chdir("."); #ifdef GRAMBUILD CLASSES = "parser scanner "; if (exists("parser")) // subdir parser exists parser(); if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY if (!so_lib) // keep all files with so libs files = altered(files, library);// keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { printf("\n"); exec(COMPILER, "-o", exe, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef GRAMBUILD "-lfl", #endif "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* L I N K S O . I M */ void link_solib(string library) { string gdb; #ifdef GDB gdb = GDB; #endif #ifdef BUILD_LIBRARY int index; list sofiles, version; version = strtok(BUILD_LIBRARY, "."); libso = "lib" + library + ".so"; libxxx = libso + "."; libsomajor = libxxx + element(0, version); libxxx += BUILD_LIBRARY; for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir(current); // chdir to a class directory. prefix_class((string)index); chdir(cwd); // go back to parent dir } if (!makelist("o/*.o")) ofiles = "*/o/*.o"; printf("\n"); exec(COMPILER, gdb, "-shared", "-Wl,-soname," + libsomajor, "-o", libxxx, ofiles, libs, "-L.", libpath, lopt ); printf("ok: ", libxxx, "\n"); for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir(current); // chdir to a class directory. rm_class_prefix((string)index); chdir(cwd); // go back to parent dir } exec("ln", "-sf", libxxx, libsomajor); printf("ok: ", libsomajor, "\n"); exec("ln", "-sf", libsomajor, libso); printf("ok: ", libso, "\n"); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int index; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY if (!so_lib) libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { current = element(index, classes); // next class to process chdir(current); // change to directory current = "subdir " + current; std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY if (!so_lib) { // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir } else { link_solib(library); // separate processing for so-lib return; } #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); #ifdef GRAMBUILD libs += " -lfl"; #endif cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "hostname.cc", // program source "hostname", // static program library "hostname" // binary program ); #else cpp_make ( "", "hostname", // static- or so-library "" ); #endif } bobcat-3.19.01/hostname/hostname2.cc0000644000175000017500000000137512222576524016145 0ustar frankfrank#include "hostname.ih" /* initialize the Hostent part by - obtaining a hostent struct from the GetHostent::gethostent() function, - providing it with the dotted-decimal address obtained from the GetHostent::addressToString() function, - which function is given the binary address obtained from the InetAddress parameter. */ namespace { static char const name[] = "Hostname::Hostname(InetAddress)"; } Hostname::Hostname(InetAddress const &address) : Hostent ( GetHostent::gethostent ( ::name, GetHostent::addressToString ( ::name, address.sockaddrPtr() ) ) ) { init(); } bobcat-3.19.01/hostname/driver/0000755000175000017500000000000012222576524015223 5ustar frankfrankbobcat-3.19.01/hostname/driver/build0000755000175000017500000000045012222576524016247 0ustar frankfrank#!/bin/bash tput clear GPP="g++ --std=c++0x" CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp -lhostname -lbobcat -s" # CMD="$GPP -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib -lbobcat -s" # CMD="$GPP -o driver -Wall *.cc -lbobcat -s" echo $CMD $CMD || exit 1 echo Ready... driver bobcat-3.19.01/hostname/driver/driver.cc0000644000175000017500000000167012222576524017031 0ustar frankfrank#include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { while (true) { cout << "Enter name or address:\n"; string str; if (!getline(cin, str)) return 0; if (str == "") break; try { Hostname h(str); cout << "Official name:\n"; cout << h.hostname() << endl; cout << "Aliases:\n"; for (size_t idx = 0; idx < h.nAliases(); idx++) cout << h.alias(idx) << " "; cout << endl; cout << "Adresses:\n"; for (size_t idx = 0; idx < h.nAddresses(); idx++) cout << h.dottedDecimalAddress(idx) << " "; cout << endl; } catch (Errno const &err) { cout << err.why() << endl; } } return 0; } bobcat-3.19.01/hostname/hostname1.cc0000644000175000017500000000023612222576524016137 0ustar frankfrank#include "hostname.ih" Hostname::Hostname(string const &host) : Hostent(GetHostent::gethostent("Hostname::Hostname(std::string)", host)) { init(); } bobcat-3.19.01/hostname/init.cc0000644000175000017500000000026512222576524015205 0ustar frankfrank#include "hostname.ih" void Hostname::init() { if (addressType() != AF_INET) throw Exception() << "Hostname::init(): no AF_INET address type found"; } bobcat-3.19.01/ibase64stream/0000755000175000017500000000000012223023055014546 5ustar frankfrankbobcat-3.19.01/ibase64stream/driver/0000755000175000017500000000000012222576534016057 5ustar frankfrankbobcat-3.19.01/ibase64stream/driver/driver.cc0000644000175000017500000000022012222576534017653 0ustar frankfrank#include "../ibase64stream" #include using namespace std; using namespace FBB; int main() { IBase64Stream in(cin); } bobcat-3.19.01/ibase64stream/ibase64stream0000644000175000017500000000066212223023055017146 0ustar frankfrank#ifndef INCLUDED_BOBCAT_IBASE64STREAM_ #define INCLUDED_BOBCAT_IBASE64STREAM_ #include #include // #include "../ibase64streambuf/ibase64streambuf" namespace FBB { template struct IBase64Stream: private IBase64Streambuf, public std::istream { IBase64Stream(std::istream &in, size_t bufSize = 1000); // 1.f }; #include "ibase64stream1.f" } // FBB #endif bobcat-3.19.01/ibase64stream/ibase64stream1.f0000644000175000017500000000024412223023055017447 0ustar frankfranktemplate IBase64Stream::IBase64Stream(std::istream &in, size_t bufSize) : IBase64Streambuf(in, bufSize), std::istream(this) {} bobcat-3.19.01/ibase64stream/ibase64stream.ih0000644000175000017500000000010412222576534017552 0ustar frankfrank#include "ibase64stream" using namespace std; using namespace FBB; bobcat-3.19.01/ibase64streambuf/0000755000175000017500000000000012223023055015243 5ustar frankfrankbobcat-3.19.01/ibase64streambuf/ibase64streambuf1.f0000644000175000017500000000021212223023055020634 0ustar frankfrankIBase64Streambuf::IBase64Streambuf(std::istream &in, size_t bufSize) : Base64StreambufBase(in, bufSize) { doEncrypt(); } bobcat-3.19.01/ibase64streambuf/driver/0000755000175000017500000000000012222576540016551 5ustar frankfrankbobcat-3.19.01/ibase64streambuf/driver/build0000644000175000017500000000021412222576540017570 0ustar frankfrank#!/bin/bash # For development purposes: g++ --std=c++0x -O2 -Wall -o driver -isystem ../../tmp driver.cc \ -L ../../tmp/lib/ -lbobcat bobcat-3.19.01/ibase64streambuf/driver/driver.cc0000644000175000017500000000171012222576540020352 0ustar frankfrank#include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { switch (argv[1][0]) { case 'e': { IBase64Streambuf encode(cin); istream ein(&encode); cout << ein.rdbuf(); } break; case 'd': { IBase64Streambuf decode(cin); istream din(&decode); cout << din.rdbuf(); } break; case 'b': { IBase64Streambuf encode(cin); istream ein(&encode); IBase64Streambuf decode(ein); istream din(&decode); cout << din.rdbuf(); } break; default: cout << "Usage: " << argv[0] << " [edb] < infile > outfile\n" "to base64 -e-ncode, -d-ecode or -b-oth\n"; break; } } bobcat-3.19.01/ibase64streambuf/ibase64streambuf.ih0000644000175000017500000000013412222576540020744 0ustar frankfrank#include "ibase64streambuf" using namespace std; using namespace FBB; using namespace IUO; bobcat-3.19.01/ibase64streambuf/ibase64streambuf2.f0000644000175000017500000000021212223023055020635 0ustar frankfrankIBase64Streambuf::IBase64Streambuf(std::istream &in, size_t bufSize) : Base64StreambufBase(in, bufSize) { doDecrypt(); } bobcat-3.19.01/ibase64streambuf/ibase64streambuf0000644000175000017500000000117612223023055020341 0ustar frankfrank#ifndef INCLUDED_BOBCAT_IBASE64STREAMBUF_ #define INCLUDED_BOBCAT_IBASE64STREAMBUF_ #include #include namespace FBB { template class IBase64Streambuf; template <> class IBase64Streambuf: public IUO::Base64StreambufBase { public: IBase64Streambuf(std::istream &in, size_t bufSize = 1000); // 1.f }; template <> class IBase64Streambuf: public IUO::Base64StreambufBase { public: IBase64Streambuf(std::istream &in, size_t bufSize = 1000); // 2.f }; #include "ibase64streambuf1.f" #include "ibase64streambuf2.f" } // FBB #endif bobcat-3.19.01/icmake/0000755000175000017500000000000012257522663013346 5ustar frankfrankbobcat-3.19.01/icmake/libraries0000644000175000017500000000663512242427272015251 0ustar frankfrankvoid buildHeader(string destination, string class, list iFiles) { list record; string line; echo(OFF); run("rm -f " + g_cwd + g_tmphdr + class); printf("Header ", g_tmphdr, class, "\n"); while (1) { record = fgets(class, (int)record[1]); if (!record) break; line = record[0]; if (strfind(line, "#include \"") != 0) fprintf(destination, line); else exec("cat " + strtok(line, "\"")[1] + " >> " + destination); } echo(ECHO_COMMANDS); } void iFiles(string class) { int idx; string destination; list iFiles; int recreate = 0; destination = g_cwd + g_tmphdr + class; chdir(class); // the destination file name iFiles = makelist("*.f"); // create list of all f-files if (class newer destination) recreate = 1; else { for (idx = sizeof(iFiles); idx--; ) { if (iFiles[idx] newer destination) { recreate = 1; break; } } } if (recreate) buildHeader(destination, class, iFiles); chdir(g_cwd); } void cpHeaders() { int idx; string file; string class; for (idx = g_nClasses; idx--; ) iFiles(g_classes[idx]); } void static_library(string library) { if (sizeof(makelist("*/oa/*.o"))) { printf("\n" "Creating static library ", library, "\n"); run("ar cru " + library + " */oa/*.o"); run("ranlib " + library); run("rm */oa/*.o"); } } void shared_library(string destDir, string libso, string libsoshared, int strip) { string libsomajor; string gxx; gxx = g_cxx + " " + g_copt; if (sizeof(makelist("*/os/*.o"))) { printf("\n" "Creating shared library ", libso, "\n"); libsomajor = libso + "." + element(0, strtok(g_version, ".")); run(gxx + " " + setOpt(LDFLAGS, "LDFLAGS") + " -shared -Wl,--as-needed," "-z,defs,-soname," + libsomajor + " -o " + destDir + libsoshared + " */os/*.o " + g_sharedLibReq); chdir(destDir); if (strip) run("strip --strip-unneeded " + libsoshared); run("chmod -x " + libsoshared); run("ln -sf " + libsoshared + " " + libsomajor); run("ln -sf " + libsomajor + " " + libso); // run("rm -f */os/*"); chdir(g_cwd); } } void libraries(string libname, int all, int strip) { string libso; string libsoshared; string staticLib; staticLib = g_tmplib + "lib" LIBRARY ".a"; addClasses("CLASSES"); special(1, all); md(g_tmplib + " " + g_tmphdr); cpHeaders(); g_copt += " -isystem tmp"; library("oa", staticLib); // compile for static lib. static_library(staticLib); // build static library #ifndef ONLY_STATIC libso = "lib" LIBRARY ".so"; libsoshared = libso + "." + g_version; g_copt += " -fPIC"; // adds option for shared lib library("os", g_tmplib + libsoshared); // compile the shared lib shared_library(g_tmplib, libso, libsoshared, strip); #endif exit(0); } bobcat-3.19.01/icmake/clean0000644000175000017500000000104212257522663014350 0ustar frankfrankstring remove1; string remove2; string remove3; void setRemovals() { // always: remove1 = "debian/lib" LIBRARY "3 debian/lib" LIBRARY "3-dev " "build-stamp configure-stamp debian/*substvars"; // unless `minimal': remove2 = "tmp release.yo */tmp */oa */os */o"; // in ./documentation: remove3 = "man/man-stamp"; } void clean() { setRemovals(); run("rm -rf " + remove1); run("rm -rf " + remove2); chdir("documentation"); run("rm -rf " + remove3); exit(0); } bobcat-3.19.01/icmake/man0000644000175000017500000000257512257522663014055 0ustar frankfrankvoid man() { list yo; list inc; string base; string yodl; int idx; int forced; special(0, 0); md("tmp/man/man1 tmp/man/man3 tmp/man/man7 tmp/manhtml"); chdir("documentation/man"); inc = makelist("*.fnc"); for (idx = sizeof(inc); idx--; ) { if (element(idx, inc) younger "man-stamp") { forced = 1; break; } } yo = makelist("*.yo") - (list)LIBRARY ".yo"; for (idx = sizeof(yo); idx--; ) { yodl = element(idx, yo); if (forced || yodl younger "man-stamp") { base = get_base(yodl); run("yodl2man --no-warnings -r 3 -l 3 -o ../../tmp/man/man3/" + base + ".3" LIBRARY " " + yodl); run("yodl2html --no-warnings -r 3 -l 3 -o ../../tmp/manhtml/" + base + ".3.html " + yodl); } } if (forced || LIBRARY ".yo" younger "man-stamp") { run("yodl2man --no-warnings -r 3 -o ../../tmp/man/man7/" LIBRARY ".7 " LIBRARY ".yo"); run("yodl2html --no-warnings -r 3 " "-o ../../tmp/manhtml/" LIBRARY ".7.html " LIBRARY ".yo"); } run("touch man-stamp"); exit(0); } bobcat-3.19.01/icmake/special0000644000175000017500000001234412222612715014703 0ustar frankfrank void askMilter(int all) { if (!all) printf( " The class FBB::Milter can only be compiled if you have installed\n" " the file libmilter/mfapi.h. To use the class Milter, programs using\n" " Milter objects must also be linked against the milter library:\n" " -lmilter -l" LIBRARY "\n" "\n" " The class FBB::Milter can safely be left out of the " LIBRARY " " "library if\n" " you're not planning to construct mail filters using FBB::Milter.\n" "\n" " Press Enter y if you WANT to compile the files of the class " "FBB::Milter.\n" " Press Enter or any other line if you DON'T WANT to include the " "class\n" " FBB::Milter in the " LIBRARY " library.\n" ); if (all || gets() == "y") { g_sharedLibReq += " -lmilter -L/usr/lib/libmilter"; g_classes += (list)"milter"; } } void askXpointer(int all) { if (!all) printf( " The class FBB::Xpointer can only be compiled if you have installed\n" " the file X11/Xlib.h. To use the class Xpointer, programs using " "Xpointer\n" " objects must also be linked against the X11 library: -lX11 -l" LIBRARY "\n" "\n" " The class FBB::Xpointer can safely be left out of the " LIBRARY " " "library if\n" " you're not planning to construct programs using Xpointer.\n" "\n" " Press Enter y if you WANT to compile the files of the class " "FBB::Xpointer.\n" " Press Enter or any other line if you DON'T WANT to include the " "class\n" " FBB::Xpointer in the " LIBRARY " library.\n" ); if (all || gets() == "y") { g_sharedLibReq += " -lX11"; g_classes += (list)"xpointer"; } } void askOpenSSL(int all) { if (!all) printf( " The SSL classes can only be compiled if you have installed\n" " the libssl-dev development library, containing files like\n" " /usr/include/openssl/bn.h. To use objects from openssl programs\n" " must also be linked against the openSSL library: -lssl -l" LIBRARY "\n" "\n" " The SSL classes can safely be left out of the " LIBRARY " library if\n" " you're not planning to construct programs using them.\n" "\n" " Press Enter y if you WANT to compile the files of the SSL classes\n" " Press Enter or any other line if you DON'T WANT to include the " "SSL classes\n" " in the " LIBRARY " library.\n" ); if (all || gets() == "y") { g_sharedLibReq += " -lssl -lcrypto"; addClasses("SSLCLASSES"); } } void askReadLine(int all) { if (!all) printf( " The classes using the readline library can only be compiled if you\n" " have installed the libreadline-dev development library, containing\n" " files like /usr/include/readline.h. To use objects of these\n" " classes in your programs, your programs must also be linked\n" " against the readline library: -lreadline -l" LIBRARY "\n" "\n" " The classes depending on the readline library can safely be left\n" " out of the " LIBRARY " library if you're not planning to construct\n" " programs using them.\n" "\n" " Press Enter y if you WANT to compile the classes using the\n" " readline library\n" " Press Enter or any other line if you DON'T WANT to include these " " classes in the " LIBRARY " library.\n" ); if (all || gets() == "y") { g_sharedLibReq += " -lreadline"; addClasses("READLINE"); } } void special(int expand, int all) { list cut; list line; int refresh; if (expand) { #ifndef ONLYCLASSES askXpointer(all); askOpenSSL(all); askReadLine(all); askMilter(all); #endif g_nClasses = sizeof(g_classes); } refresh = "VERSION" newer "release.yo"; if (refresh) run("rm -f release.yo"); while (sizeof(line = fgets("VERSION", (int)element(1, line)))) { cut = strtok(element(0, line), "= \t\n"); if (element(0, cut) == "VERSION") { g_version = element(1, cut); if (refresh) fprintf("release.yo", "SUBST(_CurVers_)(", g_version, ")\n"); } else if (refresh && element(0, cut) == "YEARS") fprintf("release.yo", "SUBST(_CurYrs_)(", element(1, cut), ")\n"); } } bobcat-3.19.01/icmake/library0000644000175000017500000000457012242427177014741 0ustar frankfrank list inspect(string dstDir, int prefix, list srcList, string library) { int idx; string ofile; string oprefix; oprefix = "./" + dstDir + "/" + (string)prefix; for (idx = sizeof(srcList); idx--; ) { g_file = element(idx, srcList); ofile = oprefix + change_ext(g_file, "o"); // make o-filename // A file s must be recompiled if it's newer than its object // file o or (with static libraries) newer than its target library l, // or if neither o nor (with static libraries) l exist. // Since `a newer b' is true if a is newer than b, or if a exists and // b doesn't exist s must be compiled if s newer o and (with static // libraries) s newer l. // So, it doesn't have to be compiled if s older o or (with static // libraries) s older l. // redo if file has changed if ( g_file older ofile || dstDir == "oa" && g_file older library ) srcList -= (list)g_file; } return srcList; } // c_compile: compile all sources in `{srcDir}/{cfiles}', storing the object // files in {srcDir}/o/{prefix}filename.o // // uses: g_opt, md, run // void c_compile(string dstDir, int prefix, string srcDir, list cfiles) { int idx; string compdest; string pthread; printf("\n" "Compiling ", srcDir, "\n"); if (strfind(PTHREAD, srcDir) != -1) pthread = " -pthread"; compdest = g_cxx + " " + g_copt + pthread + " -c -o " + srcDir + "/" + dstDir + "/" + (string)prefix; md(srcDir + "/" + dstDir); for (idx = sizeof(cfiles); idx--; ) { g_file = element(idx, cfiles); run(compdest + change_ext(g_file, "o") + " " + srcDir + "/" + g_file); } } void std_cpp(string dstDir, int prefix, string srcDir, string library) { list files; chdir(srcDir); // make list of all files files = inspect(dstDir, prefix, makelist(g_sources), library); chdir(g_cwd); if (sizeof(files)) c_compile(dstDir, prefix, srcDir, files); // compile files } void library(string dstDir, string libname) { int idx; g_sources = "*.cc"; for (idx = g_nClasses; idx--; ) std_cpp(dstDir, idx, element(idx, g_classes), "../" + libname); } bobcat-3.19.01/icmake/run0000644000175000017500000000044712242426217014072 0ustar frankfrankvoid run(string cmd) { system(0, cmd); } void md(string target) { int idx; list paths; paths = strtok(target, " "); for (idx = sizeof(paths); idx--; ) { g_file = element(idx, paths); if (!exists(g_file)) run("mkdir -p " + g_file); } } bobcat-3.19.01/icmake/install0000644000175000017500000000506712242417245014740 0ustar frankfrankvoid rungzip9(string src, string dest) { int idx; string file; list man; chdir(src); man = makelist("*"); chdir(g_cwd); for (idx = sizeof(man); idx--; ) { file = element(idx, man); run("gzip -n -9 < " + src + file + " > " + dest + file + ".gz"); } } void reqzip(string dest, string src) { list files; int idx; string file; md(dest); files = strtok(src, " "); for (idx = sizeof(files); idx--; ) { file = element(idx, files); run("gzip -n -9 < " + file + " > " + dest + file + ".gz"); } } void install(string rss, string dev) { #ifdef LIBRARIES printf("\n installing the libraries\n"); #ifndef ONLY_STATIC md(rss + LIB); run("cp " CPOPTS " tmp/lib/*so.* " + rss + LIB); md(dev + LIB); run("cp " CPOPTS " tmp/lib/*.a tmp/lib/*.so " + dev + LIB); #else md(dev + LIB); run("cp " CPOPTS " tmp/lib/*.a " + dev + LIB); #endif #endif #ifdef HEADERS printf("\n installing the headers\n"); md(dev + INC); run("cp tmp/" LIBRARY "/* " + dev + INC); #endif #ifdef MANPAGES printf("\n installing the manual pages\n"); md(dev + MAN + "/man1 " + dev + MAN + "/man3 " + dev + MAN + "/man7"); rungzip9("tmp/man/man3/", dev + MAN + "/man3/"); run("gzip -n -9 < tmp/man/man7/" LIBRARY ".7 > " + dev + MAN + "/man7/" LIBRARY ".7.gz"); #endif #ifdef MANHTML printf("\n installing the html versions of the manual pages\n"); md(dev + DOCDEV + "/man"); // Don't zip as per man dh_compress: // rungzip9("tmp/manhtml/", dev + DOCDEV + "/man/"); run("cp -r tmp/manhtml/* " + dev + DOCDEV + "/man/"); run("ln -sf " LIBRARY ".7.html " + dev + DOCDEV + "/man/index.html"); run("cp documentation/man/" LIBRARY ".jpg " + dev + DOCDEV + "/man"); #endif #ifdef DOCOTHER printf("\n installing remaining documentation\n"); reqzip(dev + DOCDEV + "/", "READLINE " "README " "README.X11 " "README.class-setup " "README.immovable " "README.milter " "README.optimization " "README.process-pipe " "README.fnwrap " "process-pipe.odp " "process-pipe.pdf " "TODO"); run("cp -r documentation/examples " + dev + DOCDEV); md(dev + DOCDEV + "/scripts"); rungzip9("scripts/", dev + DOCDEV + "/scripts/"); if (DOC != "") { md(rss + DOC); reqzip(rss + DOC + "/", "README"); } #endif printf("\n Installation completed\n"); exit(0); } bobcat-3.19.01/icmake/addclasses0000644000175000017500000000040312222576530015366 0ustar frankfrankvoid addClasses(string filename) { list class; string elem; while (sizeof(class = fgets(filename, (int)class[1]))) { elem = element(0, strtok(class[0], " \t\n")); if (elem != "#") g_classes += (list)elem; } } bobcat-3.19.01/icmake/getenv0000644000175000017500000000034012222576530014550 0ustar frankfrankstring setOpt(string install_im, string envvar) { list optvar; string ret; optvar = getenv(envvar); if (optvar[0] == "1") ret = optvar[1]; else ret = install_im; return ret; } bobcat-3.19.01/ifdstream/0000755000175000017500000000000012223023055014053 5ustar frankfrankbobcat-3.19.01/ifdstream/ifdstream0000644000175000017500000000050512223023055015754 0ustar frankfrank#ifndef INCLUDED_BOBCAT_IFDSTREAM_ #define INCLUDED_BOBCAT_IFDSTREAM_ #include #include namespace FBB { class IFdStream: private IFdStreambuf, public std::istream { public: explicit IFdStream(int fd, size_t n = 1); // 1.f }; #include "ifdstream1.f" } // FBB #endif bobcat-3.19.01/ifdstream/ifdstream1.f0000644000175000017500000000014312223023055016257 0ustar frankfrankinline IFdStream::IFdStream(int fd, size_t n) : IFdStreambuf(fd, n), std::istream(this) {} bobcat-3.19.01/ifdstreambuf/0000755000175000017500000000000012242431634014557 5ustar frankfrankbobcat-3.19.01/ifdstreambuf/destructor.cc0000644000175000017500000000012412222576524017267 0ustar frankfrank#include "ifdstreambuf.ih" IFdStreambuf::~IFdStreambuf() { cleanup(d_mode); } bobcat-3.19.01/ifdstreambuf/open.f0000644000175000017500000000012012223023055015651 0ustar frankfrankinline void IFdStreambuf::open(int xfd, size_t n) { open(xfd, d_mode, n); } bobcat-3.19.01/ifdstreambuf/underflow.cc0000644000175000017500000000075212222576524017105 0ustar frankfrank#include "ifdstreambuf.ih" int IFdStreambuf::underflow() { // if (gptr() < egptr()) // return static_cast(*gptr()); int nread = read(d_fd, d_buffer, d_n); if (nread <= 0) return EOF; setg(d_buffer, d_buffer, d_buffer + nread); // the static_cast is required to prevent // promotions of 0xff characters to -1, thus returning EOF... return static_cast(*gptr()); } bobcat-3.19.01/ifdstreambuf/ifdstreambuf0000644000175000017500000000325212223023055017150 0ustar frankfrank#ifndef INCLUDED_BOBCAT_IFDSTREAMBUF_ #define INCLUDED_BOBCAT_IFDSTREAMBUF_ #include namespace FBB { class IFdStreambuf: public std::streambuf { public: // Mode defines what to do with the file descriptor at // destruction-time or when the default open is // called. CLOSE_FD will close the fd, KEEP_FD will leave the // fd as-is. When open is called with a Mode argument, then // the provided argument is used for the actual fd. The Mode // specified at the constructor is therefore only used for the // mode-less open() call and for the destructor. enum Mode { CLOSE_FD, KEEP_FD, }; private: Mode d_mode; int d_fd; size_t d_n; char* d_buffer; public: IFdStreambuf(); explicit IFdStreambuf(Mode mode); explicit IFdStreambuf(int fd, size_t n = 1); IFdStreambuf(int fd, Mode mode, size_t n = 1); IFdStreambuf(IFdStreambuf const &other) = delete; ~IFdStreambuf(); IFdStreambuf &operator=(IFdStreambuf const &other) = delete; void close(); // .f void open(int xfd, Mode mode, size_t n = 1); void open(int xfd, size_t n = 1); // .f int fd() const; // .f private: virtual int underflow(); virtual std::streamsize xsgetn(char *dest, std::streamsize n); void cleanup(Mode mode); }; #include "open.f" #include "close.f" #include "fd.f" } // FBB #endif bobcat-3.19.01/ifdstreambuf/ifdstreambuf2.cc0000644000175000017500000000020312222576524017624 0ustar frankfrank#include "ifdstreambuf.ih" IFdStreambuf::IFdStreambuf(Mode mode) : d_mode(mode), d_fd(-1), d_n(0), d_buffer(0) {} bobcat-3.19.01/ifdstreambuf/ifdstreambuf1.cc0000644000175000017500000000024112222576524017625 0ustar frankfrank#include "ifdstreambuf.ih" IFdStreambuf::IFdStreambuf() : d_mode(KEEP_FD), // comply with old default d_fd(-1), d_n(0), d_buffer(0) {} bobcat-3.19.01/ifdstreambuf/open.cc0000644000175000017500000000035112222576524016034 0ustar frankfrank#include "ifdstreambuf.ih" void IFdStreambuf::open(int xfd, Mode mode, size_t n) { cleanup(mode); d_fd = xfd; d_n = (n == 0) ? 1 : n; d_buffer = new char[d_n]; setg(d_buffer, d_buffer + d_n, d_buffer + d_n); } bobcat-3.19.01/ifdstreambuf/cleanup.cc0000644000175000017500000000034312222576524016523 0ustar frankfrank#include "ifdstreambuf.ih" void IFdStreambuf::cleanup(Mode mode) { if (d_buffer) { if (mode == CLOSE_FD) ::close(d_fd); delete [] d_buffer; d_buffer = 0; d_fd = -1; } } bobcat-3.19.01/ifdstreambuf/ifdstreambuf.ih0000644000175000017500000000015112222576524017557 0ustar frankfrank#include "ifdstreambuf" #include #include #include using namespace FBB; bobcat-3.19.01/ifdstreambuf/ifdstreambuf3.cc0000644000175000017500000000026012222576524017630 0ustar frankfrank#include "ifdstreambuf.ih" IFdStreambuf::IFdStreambuf(int fd, size_t n) : d_mode(KEEP_FD), // comply with old default d_buffer(0) { open(fd, KEEP_FD, n); } bobcat-3.19.01/ifdstreambuf/close.f0000644000175000017500000000007512223023055016026 0ustar frankfrankinline void IFdStreambuf::close() { cleanup(CLOSE_FD); } bobcat-3.19.01/ifdstreambuf/ifdstreambuf4.cc0000644000175000017500000000022612222576524017633 0ustar frankfrank#include "ifdstreambuf.ih" IFdStreambuf::IFdStreambuf(int fd, Mode mode, size_t n) : d_mode(mode), d_buffer(0) { open(fd, KEEP_FD, n); } bobcat-3.19.01/ifdstreambuf/fd.f0000644000175000017500000000007112223023055015306 0ustar frankfrankinline int IFdStreambuf::fd() const { return d_fd; } bobcat-3.19.01/ifdstreambuf/xsgetn.cc0000644000175000017500000000143012222576524016402 0ustar frankfrank#include "ifdstreambuf.ih" std::streamsize IFdStreambuf::xsgetn(char *dest, std::streamsize n) { if (n == 0) return 0; // this function is called from istream's read() member. // it copies what's available in the IFdStreambuf's own buffer and // will then try to read some more from the fd, adding it to the // destination buffer. Unless the requested amount of information is // available the stream's good() member will return false. Calling // programs may have to clear the stream's flags when, e.g., // at least one byte was read int avail = egptr() - gptr(); if (avail > n) avail = n; memcpy(dest, gptr(), avail); gbump(avail); return avail + read(d_fd, dest + avail, n - avail); } bobcat-3.19.01/ifilterstreambuf/0000755000175000017500000000000012242431634015453 5ustar frankfrankbobcat-3.19.01/ifilterstreambuf/destructor.cc0000644000175000017500000000011212222576530020155 0ustar frankfrank#include "ifilterstreambuf.ih" IFilterStreambuf::~IFilterStreambuf() { } bobcat-3.19.01/ifilterstreambuf/underflow.cc0000644000175000017500000000225212222576530017773 0ustar frankfrank#include "ifilterstreambuf.ih" #include int IFilterStreambuf::underflow() { if (d_srcBegin == d_srcEnd) // no source bytes, then { // get some. If none available if (not filter(&d_srcBegin, &d_srcEnd)) // return EOF return EOF; } size_t srcSize = d_srcEnd - d_srcBegin; // #available source bytes // as long as all src bytes fit in the buffer they can all be stored if (srcSize <= d_remaining) src2buffer(srcSize); // else, if there is remaining space, use it to store some of the // source bytes else if (d_remaining) src2buffer(d_remaining); // else, create some remaining space by removing initial bytes from // the buffer, which therefore can no longer be ungot. else if (srcSize <= d_maxRefresh) makeAvailable(srcSize); // else load at most d_maxRefresh of the available source bytes else makeAvailable(d_maxRefresh); setg(d_begin, d_next, d_end); // reload the input buffer return *gptr(); // return the next available char } bobcat-3.19.01/ifilterstreambuf/ifilterstreambuf0000644000175000017500000000177112223023055020744 0ustar frankfrank#ifndef INCLUDED_BOBCAT_IFILTERSTREAMBUF_ #define INCLUDED_BOBCAT_IFILTERSTREAMBUF_ #include #include namespace FBB { class IFilterStreambuf: public std::streambuf { size_t d_bufSize; size_t d_maxRefresh; size_t d_remaining; char const *d_srcBegin = 0; char const *d_srcEnd = 0; std::unique_ptr d_buffer; char *d_begin; char *d_next; char *d_end; public: virtual ~IFilterStreambuf(); protected: IFilterStreambuf(size_t bufSize = 1000); void setBuffer(); // .f private: virtual bool filter(char const **srcBegin, char const **srcEnd) = 0; int underflow() final override; std::streamsize showmanyc() final override; int pbackfail(int ch) final override; void src2buffer(size_t nBytes); void makeAvailable(size_t nBytes); }; #include "setbuffer.f" } // FBB #endif bobcat-3.19.01/ifilterstreambuf/makeavailable.cc0000644000175000017500000000036112222576530020543 0ustar frankfrank#include "ifilterstreambuf.ih" void IFilterStreambuf::makeAvailable(size_t nBytes) { memmove(d_begin, d_begin + nBytes, d_bufSize - nBytes); d_end -= nBytes; d_next = d_end; d_remaining += nBytes; src2buffer(nBytes); } bobcat-3.19.01/ifilterstreambuf/ifilterstreambuf1.cc0000644000175000017500000000050012222576530021410 0ustar frankfrank#include "ifilterstreambuf.ih" IFilterStreambuf::IFilterStreambuf(size_t bufSize) : d_bufSize(bufSize < 100 ? 100 : bufSize), d_maxRefresh(d_bufSize >> 1), d_remaining(d_bufSize), d_buffer(new char[d_bufSize]), d_begin(d_buffer.get()), d_next(d_begin), d_end(d_begin) { setg(0, 0, 0); } bobcat-3.19.01/ifilterstreambuf/driver/0000755000175000017500000000000012222576530016751 5ustar frankfrankbobcat-3.19.01/ifilterstreambuf/driver/driver.cc0000644000175000017500000000310412222576530020551 0ustar frankfrank#include #include #include #include class CharFilterStreambuf: public FBB::IFilterStreambuf { std::istream &d_in; // stream to read from std::string d_rmChars; // chars to rm std::string d_buffer; // locally buffered chars size_t const d_maxSize = 100; public: CharFilterStreambuf(std::istream &in, std::string const &rmChars); private: bool filter(char const **srcBegin, char const **srcEnd) override; }; CharFilterStreambuf::CharFilterStreambuf(std::istream &in, std::string const &rmChars) : d_in(in), d_rmChars(rmChars) { setBuffer(); // required if peek() must return the 1st } // available character right from the start bool CharFilterStreambuf::filter(char const **srcBegin, char const **srcEnd) { d_buffer.clear(); while (d_buffer.size() != d_maxSize) { char ch; if (not d_in.get(ch)) break; if (d_rmChars.find(ch) != std::string::npos) // found char to rm continue; d_buffer.push_back(ch); } if (d_buffer.empty()) return false; *srcBegin = d_buffer.data(); *srcEnd = d_buffer.data() + d_buffer.size(); return true; } int main() { CharFilterStreambuf buf1(std::cin, "1234567890"); std::istream in1(&buf1); CharFilterStreambuf buf2(in1, "AEIOUaeiou"); std::istream in2(&buf2); std::cout << in2.rdbuf(); } bobcat-3.19.01/ifilterstreambuf/setbuffer.f0000644000175000017500000000007712223023055017604 0ustar frankfrankinline void IFilterStreambuf::setBuffer() { underflow(); } bobcat-3.19.01/ifilterstreambuf/showmanyc.cc0000644000175000017500000000016412222576530017776 0ustar frankfrank#include "ifilterstreambuf.ih" std::streamsize IFilterStreambuf::showmanyc() { return d_srcEnd - d_srcBegin; } bobcat-3.19.01/ifilterstreambuf/src2buffer.cc0000644000175000017500000000033212222576530020026 0ustar frankfrank#include "ifilterstreambuf.ih" void IFilterStreambuf::src2buffer(size_t nBytes) { memcpy(d_end, d_srcBegin, nBytes); d_srcBegin += nBytes; d_next = d_end; d_end += nBytes; d_remaining -= nBytes; } bobcat-3.19.01/ifilterstreambuf/pbackfail.cc0000644000175000017500000000013412222576530017677 0ustar frankfrank#include "ifilterstreambuf.ih" int IFilterStreambuf::pbackfail(int ch) { return EOF; } bobcat-3.19.01/ifilterstreambuf/ifilterstreambuf.ih0000644000175000017500000000015712222576530021352 0ustar frankfrank#include "ifilterstreambuf" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/indent/0000755000175000017500000000000012242431634013365 5ustar frankfrankbobcat-3.19.01/indent/indent.cc0000644000175000017500000000022512222576536015165 0ustar frankfrank#include "indent.ih" ostream &FBB::indent(ostream &out) { if (Indent::s_width) out << setw(Indent::s_width) << ' '; return out; } bobcat-3.19.01/indent/indent.ih0000644000175000017500000000012312222576536015175 0ustar frankfrank#include "indent" #include using namespace std; using namespace FBB; bobcat-3.19.01/indent/decindent.cc0000644000175000017500000000015512222576536015643 0ustar frankfrank#include "indent.ih" ostream &FBB::decindent(ostream &out) { Indent::dec(); return out << indent; } bobcat-3.19.01/indent/dec.cc0000644000175000017500000000032512222576536014440 0ustar frankfrank#include "indent.ih" void FBB::Indent::dec() { Indent::s_width = Indent::s_width > Indent::s_inc ? Indent::s_width - Indent::s_inc : 0; } bobcat-3.19.01/indent/indentdec.cc0000644000175000017500000000017412222576536015644 0ustar frankfrank#include "indent.ih" ostream &FBB::indentdec(ostream &out) { out << indent; Indent::dec(); return out; } bobcat-3.19.01/indent/setinc.f0000644000175000017500000000007412223023055015013 0ustar frankfrankinline void Indent::setInc(size_t inc) { s_inc = inc; } bobcat-3.19.01/indent/incindent.cc0000644000175000017500000000017012222576536015656 0ustar frankfrank#include "indent.ih" std::ostream &FBB::incindent(std::ostream &out) { Indent::inc(); return out << indent; } bobcat-3.19.01/indent/clear.f0000644000175000017500000000006112223023055014610 0ustar frankfrankinline void Indent::clear() { s_width = 0; } bobcat-3.19.01/indent/data.cc0000644000175000017500000000011512222576536014613 0ustar frankfrank#include "indent.ih" size_t Indent::s_width = 0; size_t Indent::s_inc = 4; bobcat-3.19.01/indent/indentinc.cc0000644000175000017500000000016712222576536015664 0ustar frankfrank#include "indent.ih" ostream &FBB::indentinc(ostream &out) { out << indent; Indent::inc(); return out; } bobcat-3.19.01/indent/setwidth.f0000644000175000017500000000010412223023055015353 0ustar frankfrankinline void Indent::setWidth(size_t width) { s_width = width; } bobcat-3.19.01/indent/inc.f0000644000175000017500000000006412223023055014276 0ustar frankfrankinline void Indent::inc() { s_width += s_inc; } bobcat-3.19.01/indent/indent0000644000175000017500000000156612223023055014572 0ustar frankfrank#ifndef INCLUDED_BOBCAT_INDENT_ #define INCLUDED_BOBCAT_INDENT_ #include namespace FBB { class Indent { friend std::ostream &indent(std::ostream &out); static size_t s_width; static size_t s_inc; public: static void setWidth(size_t width); // .f static void setInc(size_t inc); // .f static void clear(); // .f static void inc(); // .f static void dec(); }; #include "clear.f" #include "inc.f" #include "setinc.f" #include "setwidth.f" // Free functions std::ostream &indent(std::ostream &out); #include "nlindent.f" std::ostream &incindent(std::ostream &out); std::ostream &indentinc(std::ostream &out); std::ostream &decindent(std::ostream &out); std::ostream &indentdec(std::ostream &out); } // namespace FBB #endif bobcat-3.19.01/indent/nlindent.f0000644000175000017500000000012712223023055015340 0ustar frankfrankinline std::ostream &nlindent(std::ostream &out) { return out << "\n" << indent; } bobcat-3.19.01/inetaddress/0000755000175000017500000000000012242431634014411 5ustar frankfrankbobcat-3.19.01/inetaddress/dotteddecimaladdress.cc0000644000175000017500000000030112222576534021071 0ustar frankfrank#include "inetaddress.ih" std::string InetAddress::dottedDecimalAddress() const { return GetHostent::addressToString("InetAddress::getAddress()", &d_address.sin_addr); } bobcat-3.19.01/inetaddress/sockaddrptr2.f0000644000175000017500000000014612223023055017154 0ustar frankfrankinline sockaddr *InetAddress::sockaddrPtr() { return reinterpret_cast(&d_address); } bobcat-3.19.01/inetaddress/size.f0000644000175000017500000000011212223023055015515 0ustar frankfrankinline size_t InetAddress::size() const { return sizeof(d_address); } bobcat-3.19.01/inetaddress/inetaddress.ih0000644000175000017500000000016312222576534017247 0ustar frankfrank#include "inetaddress" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/inetaddress/sockaddrinptr2.f0000644000175000017500000000011512223023055017477 0ustar frankfrankinline sockaddr_in *InetAddress::sockaddr_inPtr() { return &d_address; } bobcat-3.19.01/inetaddress/sockaddrinptr1.f0000644000175000017500000000013112223023055017474 0ustar frankfrankinline sockaddr_in const *InetAddress::sockaddr_inPtr() const { return &d_address; } bobcat-3.19.01/inetaddress/port.f0000644000175000017500000000012412223023055015532 0ustar frankfrankinline uint16_t InetAddress::port() const { return ntohs(d_address.sin_port); } bobcat-3.19.01/inetaddress/driver/0000755000175000017500000000000012222576534015713 5ustar frankfrankbobcat-3.19.01/inetaddress/driver/build0000755000175000017500000000005412222576534016737 0ustar frankfrank#!/bin/sh g++ -o driver driver.cc -lbobcat bobcat-3.19.01/inetaddress/driver/driver.cc0000644000175000017500000000121112222576534017510 0ustar frankfrank#include #include #include using namespace std; using namespace FBB; InetAddress X() { class A: public InetAddress { public: A(uint16_t port) : InetAddress(port) {} }; return A(2000); } int main(int argc, char **argv) try { InetAddress const &ia = X(); cout << "A InetAddress was constructed for port " << ia.port() << endl; cout << "It has the generic `ANY' address: " << ia.dottedDecimalAddress() << endl; return 0; } catch (Errno const &e) { cout << "Exception: " << e.why() << endl; } bobcat-3.19.01/inetaddress/inetaddress2.f0000644000175000017500000000013712223023055017141 0ustar frankfrankinline InetAddress::InetAddress(sockaddr_in const &address) : d_address(address) {} bobcat-3.19.01/inetaddress/inetaddress1.cc0000644000175000017500000000041612222576534017316 0ustar frankfrank#include "inetaddress.ih" InetAddress::InetAddress(string const &host, uint16_t port) { hostent const *hp = GetHostent::gethostent("InetAddress::InetAddress(host, port)", host); init(ntohl(*reinterpret_cast (*(hp->h_addr_list))), port); } bobcat-3.19.01/inetaddress/inetaddress0000644000175000017500000000275112223023055016637 0ustar frankfrank#ifndef INCLUDED_BOBCAT_INETADDRESS_ #define INCLUDED_BOBCAT_INETADDRESS_ #include #include /* int-info coming in or going out: host byte order */ namespace FBB { class InetAddress { sockaddr_in d_address; // address/port: network byte order // sa_family_t in_addr, uint16_t // sin_family, sin_addr, sin_port public: uint16_t port() const; // .f // replaces the formerly available getAddress() member. std::string dottedDecimalAddress() const; sockaddr const *sockaddrPtr() const; // 1.f sockaddr_in const *sockaddr_inPtr() const; // 1.f size_t size() const; // .f protected: InetAddress(std::string const &host, uint16_t port); explicit InetAddress(uint16_t port); // 1.f explicit InetAddress(sockaddr_in const &address); // 2.f sockaddr *sockaddrPtr(); // 2.f sockaddr_in *sockaddr_inPtr(); // 2.f private: void init(uint32_t addr, uint16_t port); // host byte order ! }; #include "inetaddress1.f" #include "inetaddress2.f" #include "port.f" #include "size.f" #include "sockaddrinptr1.f" #include "sockaddrinptr2.f" #include "sockaddrptr1.f" #include "sockaddrptr2.f" } // FBB #endif bobcat-3.19.01/inetaddress/inetaddress1.f0000644000175000017500000000011712223023055017136 0ustar frankfrankinline InetAddress::InetAddress(uint16_t port) { init(INADDR_ANY, port); } bobcat-3.19.01/inetaddress/init.cc0000644000175000017500000000033512222576534015673 0ustar frankfrank#include "inetaddress.ih" void InetAddress::init(uint32_t addr, uint16_t port) { d_address.sin_family = AF_INET; d_address.sin_addr.s_addr = htonl(addr); d_address.sin_port = htons(port); } bobcat-3.19.01/inetaddress/sockaddrptr1.f0000644000175000017500000000016712223023055017156 0ustar frankfrankinline sockaddr const *InetAddress::sockaddrPtr() const { return reinterpret_cast(&d_address); } bobcat-3.19.01/iostream/0000755000175000017500000000000012242431634013727 5ustar frankfrankbobcat-3.19.01/iostream/iostream1.f0000644000175000017500000000012012223023055015764 0ustar frankfrankinline IOStream::IOStream() : std::istream(this), std::ostream(this) {} bobcat-3.19.01/iostream/iostream0000644000175000017500000000102112223023055015460 0ustar frankfrank#ifndef INCLUDED_BOBCAT_IOSTREAM_ #define INCLUDED_BOBCAT_IOSTREAM_ #include namespace FBB { class IOStream: private IOStreambuf, public std::istream, public std::ostream { public: IOStream(); // 1.f IOStream(std::istream &in, std::ostream &out); // 2.f void clear(); void open(std::istream &in, std::ostream &out); // .f }; #include "iostream1.f" #include "iostream2.f" #include "open.f" } // namespace FBB #endif bobcat-3.19.01/iostream/open.f0000644000175000017500000000014412223023055015027 0ustar frankfrankinline void IOStream::open(std::istream &in, std::ostream &out) { IOStreambuf::open(in, out); } bobcat-3.19.01/iostream/clear1.cc0000644000175000017500000000014112222576523015406 0ustar frankfrank#include "iostream.ih" void IOStream::clear() { istream::clear(); ostream::clear(); } bobcat-3.19.01/iostream/iostream2.f0000644000175000017500000000020712223023055015773 0ustar frankfrankinline IOStream::IOStream(std::istream &in, std::ostream &out) : std::istream(this), std::ostream(this) { open(in, out); } bobcat-3.19.01/iostream/iostream.ih0000644000175000017500000000007712222576523016105 0ustar frankfrank#include "iostream" using namespace std; using namespace FBB; bobcat-3.19.01/iostreambuf/0000755000175000017500000000000012242431634014424 5ustar frankfrankbobcat-3.19.01/iostreambuf/iostreambuf0000644000175000017500000000336412223023055016666 0ustar frankfrank#ifndef INCLUDED_BOBCAT_IOSTREAMBUF_ #define INCLUDED_BOBCAT_IOSTREAMBUF_ #include #include namespace FBB { class IOStreambuf: public std::streambuf { char d_buf; std::istream *d_in; std::ostream *d_out; public: IOStreambuf(); // 1.f IOStreambuf(std::istream &in, std::ostream &out); // 2.f virtual ~IOStreambuf(); void open(std::istream &in, std::ostream &out); protected: std::streamsize pXsputn(char const *buffer, // .f std::streamsize n); int pSync(); pos_type pSeekoff(off_type offset, std::ios::seekdir way, std::ios::openmode mode = std::ios::in | std::ios::out); pos_type pSeekpos(pos_type offset, // .f std::ios::openmode mode = std::ios::in | std::ios::out); private: virtual int underflow(); virtual pos_type seekoff(off_type offset, std::ios::seekdir way, std::ios::openmode mode = std::ios::in | std::ios::out); virtual pos_type seekpos(pos_type offset, std::ios::openmode mode = std::ios::in | std::ios::out); virtual int sync(); virtual int overflow(int c); virtual std::streamsize xsputn(char const *buffer, std::streamsize n); }; #include "iostreambuf1.f" #include "iostreambuf2.f" #include "pseekpos.f" #include "pxsputn.f" } // namespace FBB #endif bobcat-3.19.01/iostreambuf/pseekoff.cc0000644000175000017500000000071412222625443016540 0ustar frankfrank#include "iostreambuf.ih" std::ios::pos_type IOStreambuf::pSeekoff(off_type offset, std::ios::seekdir way, std::ios::openmode mode) { if (mode == std::ios::in) { if (d_in->seekg(offset, way)) { setg(&d_buf, &d_buf + 1, &d_buf + 1); return d_in->tellg(); } } else { if (d_out->seekp(offset, way)) return d_out->tellp(); } return -1; } bobcat-3.19.01/iostreambuf/pseekpos.f0000644000175000017500000000025412223023055016416 0ustar frankfrankinline IOStreambuf::pos_type IOStreambuf::pSeekpos(pos_type offset, std::ios::openmode mode) { return seekoff(offset, std::ios::beg, mode); } bobcat-3.19.01/iostreambuf/destructor.cc0000644000175000017500000000013212222625443017126 0ustar frankfrank#include "iostreambuf.ih" IOStreambuf::~IOStreambuf() { if (d_out) sync(); } bobcat-3.19.01/iostreambuf/underflow.cc0000644000175000017500000000037612222625443016747 0ustar frankfrank#include "iostreambuf.ih" int IOStreambuf::underflow() { int c; c = d_in->get(); if (c == EOF) setg(&d_buf, &d_buf + 1, &d_buf + 1); else { d_buf = c; setg(&d_buf, &d_buf, &d_buf + 1); } return c; } bobcat-3.19.01/iostreambuf/xsputn.cc0000644000175000017500000000020412222625443016271 0ustar frankfrank#include "iostreambuf.ih" std::streamsize IOStreambuf::xsputn(char const *buffer, streamsize n) { return pXsputn(buffer, n); } bobcat-3.19.01/iostreambuf/iostreambuf2.f0000644000175000017500000000014412223023055017165 0ustar frankfrankinline IOStreambuf::IOStreambuf(std::istream &in, std::ostream &out) { open(in, out); } bobcat-3.19.01/iostreambuf/open.cc0000644000175000017500000000030712222625443015675 0ustar frankfrank#include "iostreambuf.ih" void IOStreambuf::open(std::istream &in, std::ostream &out) { if (d_out) sync(); d_in = ∈ d_out = &out; setg(&d_buf, &d_buf + 1, &d_buf + 1); } bobcat-3.19.01/iostreambuf/iostreambuf1.f0000644000175000017500000000011112223023055017156 0ustar frankfrankinline IOStreambuf::IOStreambuf() : d_in(0), d_out(0) {} bobcat-3.19.01/iostreambuf/seekpos.cc0000644000175000017500000000027712222625443016413 0ustar frankfrank#include "iostreambuf.ih" IOStreambuf::pos_type IOStreambuf::seekpos(pos_type offset, ios::openmode mode) { return pSeekpos(offset, mode); } bobcat-3.19.01/iostreambuf/pxsputn.f0000644000175000017500000000025712223023055016311 0ustar frankfrankinline std::streamsize IOStreambuf::pXsputn(char const *buffer, std::streamsize n) { return d_out->write(buffer, n) ? n : 0; } bobcat-3.19.01/iostreambuf/overflow.cc0000644000175000017500000000023012222625443016572 0ustar frankfrank#include "iostreambuf.ih" int IOStreambuf::overflow(int c) { if (c == EOF) d_out->flush(); else d_out->put(c); return c; } bobcat-3.19.01/iostreambuf/seekoff.cc0000644000175000017500000000031412222625443016354 0ustar frankfrank#include "iostreambuf.ih" streambuf::pos_type IOStreambuf::seekoff(off_type offset, ios::seekdir way, ios::openmode mode) { return pSeekoff(offset, way, mode); } bobcat-3.19.01/iostreambuf/iostreambuf.ih0000644000175000017500000000012612222576523017272 0ustar frankfrank#include "iostreambuf" #include using namespace std; using namespace FBB; bobcat-3.19.01/iostreambuf/psync.cc0000644000175000017500000000014712222625443016072 0ustar frankfrank#include "iostreambuf.ih" int IOStreambuf::pSync() { d_out->flush(); return !d_out->good(); } bobcat-3.19.01/iostreambuf/sync.cc0000644000175000017500000000012312222625443015704 0ustar frankfrank#include "iostreambuf.ih" int IOStreambuf::sync() { return pSync(); } bobcat-3.19.01/irandstream/0000755000175000017500000000000012223023055014406 5ustar frankfrankbobcat-3.19.01/irandstream/irandstream1.f0000644000175000017500000000014012223023055017142 0ustar frankfrankinline IRandStream::IRandStream(int max) : Randbuffer(1, max, 1), std::istream(this) {} bobcat-3.19.01/irandstream/driver/0000755000175000017500000000000012222576534015717 5ustar frankfrankbobcat-3.19.01/irandstream/driver/build0000755000175000017500000000005412222576534016743 0ustar frankfrank#!/bin/sh g++ -o driver driver.cc -lbobcat bobcat-3.19.01/irandstream/driver/driver.cc0000644000175000017500000000043312222576534017521 0ustar frankfrank#include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { IRandStream in(1000); for (; argc--; ) { size_t random; in >> random; cout << random << endl; } return 0; } bobcat-3.19.01/irandstream/irandstream0000644000175000017500000000070212223023055016641 0ustar frankfrank#ifndef INCLUDED_BOBCAT_IRANDSTREAM_H_ #define INCLUDED_BOBCAT_IRANDSTREAM_H_ #include #include namespace FBB { class IRandStream: private Randbuffer, public std::istream { public: explicit IRandStream(int max); IRandStream(int min, int max); IRandStream(int min, int max, int seed); }; #include "irandstream1.f" #include "irandstream2.f" #include "irandstream3.f" } // FBB #endif bobcat-3.19.01/irandstream/irandstream3.f0000644000175000017500000000017012223023055017147 0ustar frankfrankinline IRandStream::IRandStream(int min, int max, int seed) : Randbuffer(min, max, seed), std::istream(this) {} bobcat-3.19.01/irandstream/irandstream2.f0000644000175000017500000000015312223023055017147 0ustar frankfrankinline IRandStream::IRandStream(int min, int max) : Randbuffer(min, max, 1), std::istream(this) {} bobcat-3.19.01/isharedstream/0000755000175000017500000000000012244427062014741 5ustar frankfrankbobcat-3.19.01/isharedstream/open2.cc0000644000175000017500000000025012240162165016264 0ustar frankfrank#include "isharedstream.ih" void ISharedStream::open(int id, std::ios::openmode openMode) { setMemory(SharedMemory(id)); setOpenMode(openMode); clear(); } bobcat-3.19.01/isharedstream/meminfo.cc0000644000175000017500000000026512242372127016704 0ustar frankfrank#include "isharedstream.ih" void ISharedStream::memInfo(std::ostream &out, char const *end) const { static_cast(this)->memInfo(out); out << end; } bobcat-3.19.01/isharedstream/open1.cc0000644000175000017500000000041312240162165016264 0ustar frankfrank#include "isharedstream.ih" void ISharedStream::open( size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode, size_t access) { setMemory(SharedMemory(maxSize, sizeUnit, access)); setOpenMode(openMode); clear(); } bobcat-3.19.01/isharedstream/isharedstream1.cc0000644000175000017500000000012512240162254020155 0ustar frankfrank#include "isharedstream.ih" ISharedStream::ISharedStream() : istream(this) {} bobcat-3.19.01/isharedstream/isharedstream.ih0000644000175000017500000000010412237774665020131 0ustar frankfrank#include "isharedstream" using namespace std; using namespace FBB; bobcat-3.19.01/isharedstream/isharedstream3.cc0000644000175000017500000000023512240162354020162 0ustar frankfrank#include "isharedstream.ih" ISharedStream::ISharedStream(size_t id, std::ios::openmode openMode) : SharedStreambuf(id, openMode), istream(this) {} bobcat-3.19.01/isharedstream/isharedstream2.cc0000644000175000017500000000041412240162272020157 0ustar frankfrank#include "isharedstream.ih" ISharedStream::ISharedStream( size_t maxSize, SharedMemory::SizeUnit sizeUnit, std::ios::openmode openMode, size_t access) : SharedStreambuf(maxSize, sizeUnit, openMode, access), istream(this) {} bobcat-3.19.01/isharedstream/isharedstream0000644000175000017500000000200712244427062017516 0ustar frankfrank#ifndef INCLUDED_BOBCAT_ISHAREDSTREAM_ #define INCLUDED_BOBCAT_ISHAREDSTREAM_ #include #include namespace FBB { struct ISharedStream: private SharedStreambuf, public std::istream, public virtual SharedEnum__ { ISharedStream(); ISharedStream( size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::in, size_t access = 0600); ISharedStream( size_t id, std::ios::openmode openMode = std::ios::in); void open( size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::in, size_t access = 0600); void open( int id, std::ios::openmode openMode = std::ios::in); using std::istream::clear; void memInfo(std::ostream &out, char const *end = "\n") const; using SharedStreambuf::id; using SharedStreambuf::remove; using SharedStreambuf::kill; }; } // FBB #endif bobcat-3.19.01/isymcryptstream/0000755000175000017500000000000012223023055015354 5ustar frankfrankbobcat-3.19.01/isymcryptstream/isymcryptstream1.f0000644000175000017500000000062712223023055021070 0ustar frankfranktemplate ISymCryptStream::ISymCryptStream( std::istream &in, char const *type, std::string const &key, std::string const &iv, size_t bufSize, size_t filterBufSize, ENGINE *engine) : ISymCryptStreambuf( in, type, key, iv, bufSize, filterBufSize, engine ), std::istream(this) {} bobcat-3.19.01/isymcryptstream/isymcryptstream0000644000175000017500000000116412223023055020560 0ustar frankfrank#ifndef INCLUDED_BOBCAT_ISYMCRYPTSTREAM_ #define INCLUDED_BOBCAT_ISYMCRYPTSTREAM_ #include #include namespace FBB { template struct ISymCryptStream: private ISymCryptStreambuf, public std::istream { ISymCryptStream( // 1.f std::istream &in, char const *type, std::string const &key, std::string const &iv, size_t bufSize = 100, size_t filterBufSize = 1000, ENGINE *engine = 0 ); }; #include "isymcryptstream1.f" } // FBB #endif bobcat-3.19.01/isymcryptstream/isymcryptstream.ih0000644000175000017500000000010612222576530021164 0ustar frankfrank#include "isymcryptstream" using namespace std; using namespace FBB; bobcat-3.19.01/isymcryptstream/driver/0000755000175000017500000000000012224222410016644 5ustar frankfrankbobcat-3.19.01/isymcryptstream/driver/build0000755000175000017500000000022512224222373017700 0ustar frankfrank#!/bin/bash # For development purposes: g++ --std=c++0x -O2 -Wall -o driver -isystem ../../tmp driver.cc \ -L ../../tmp/lib/ -lbobcat -lcrypto bobcat-3.19.01/isymcryptstream/driver/driver.cc0000644000175000017500000000060312222576530020462 0ustar frankfrank#include "../isymcryptstream" #include using namespace std; using namespace FBB; int main() { ISymCryptStream encryptor(cin, "bf-cbc", "1234567890", "1234567890"); ISymCryptStream decryptor(encryptor, "bf-cbc", "1234567890", "1234567890"); cout << decryptor.rdbuf(); } bobcat-3.19.01/isymcryptstreambuf/0000755000175000017500000000000012223023055016051 5ustar frankfrankbobcat-3.19.01/isymcryptstreambuf/isymcryptstreambuf0000644000175000017500000000221012223023055021743 0ustar frankfrank#ifndef INCLUDED_BOBCAT_ISYMCRYPTSTREAMBUF_ #define INCLUDED_BOBCAT_ISYMCRYPTSTREAMBUF_ #include #include namespace FBB { template class ISymCryptStreambuf; template <> class ISymCryptStreambuf: public IUO::SymCryptStreambufBase { public: ISymCryptStreambuf( // 1.ff std::istream &in, char const *type, std::string const &key, std::string const &iv, size_t bufSize = 100, size_t filterBufSize = 1000, ENGINE *engine = 0 ); }; template <> class ISymCryptStreambuf: public IUO::SymCryptStreambufBase { public: ISymCryptStreambuf( // 2.ff std::istream &in, char const *type, std::string const &key, std::string const &iv, size_t bufSize = 100, size_t filterBufSize = 1000, ENGINE *engine = 0 ); }; #include "isymcryptstreambuf1.f" #include "isymcryptstreambuf2.f" } // FBB #endif bobcat-3.19.01/isymcryptstreambuf/isymcryptstreambuf2.f0000644000175000017500000000064712223023055022265 0ustar frankfrankISymCryptStreambuf::ISymCryptStreambuf( std::istream &in, char const *type, std::string const &key, std::string const &iv, size_t bufSize, size_t filterBufSize, ENGINE *engine) : SymCryptStreambufBase( &EVP_DecryptInit_ex, &EVP_DecryptUpdate, &EVP_DecryptFinal_ex, in, type, key, iv, bufSize, filterBufSize, engine ) {} bobcat-3.19.01/isymcryptstreambuf/driver/0000755000175000017500000000000012224222463017351 5ustar frankfrankbobcat-3.19.01/isymcryptstreambuf/driver/build0000755000175000017500000000022512224222457020400 0ustar frankfrank#!/bin/bash # For development purposes: g++ --std=c++0x -O2 -Wall -o driver -isystem ../../tmp driver.cc \ -L ../../tmp/lib/ -lbobcat -lcrypto bobcat-3.19.01/isymcryptstreambuf/driver/driver.cc0000644000175000017500000000065212222576531021164 0ustar frankfrank#include #include using namespace std; using namespace FBB; int main() { ISymCryptStreambuf ebuf(cin, "bf-cbc", "1234567890", "1234567890"); istream ein(&ebuf); ISymCryptStreambuf dbuf(ein, "bf-cbc", "1234567890", "1234567890"); istream din(&dbuf); cout << din.rdbuf(); } bobcat-3.19.01/isymcryptstreambuf/isymcryptstreambuf.ih0000644000175000017500000000013612222576531022362 0ustar frankfrank#include "isymcryptstreambuf" using namespace std; using namespace FBB; using namespace IUO; bobcat-3.19.01/isymcryptstreambuf/isymcryptstreambuf1.f0000644000175000017500000000075412223023055022263 0ustar frankfrankISymCryptStreambuf::ISymCryptStreambuf( std::istream &in, char const *type, std::string const &key, std::string const &iv, size_t bufSize, size_t filterBufSize, ENGINE *engine ) : SymCryptStreambufBase( &EVP_EncryptInit_ex, &EVP_EncryptUpdate, &EVP_EncryptFinal_ex, in, type, key, iv, bufSize, filterBufSize, engine ) {} bobcat-3.19.01/iuo/0000755000175000017500000000000012242431634012700 5ustar frankfrankbobcat-3.19.01/iuo/opstructarray1.cc0000644000175000017500000000021512222576534016217 0ustar frankfrank#include "iuo.ih" OptStructArray::OptStructArray(size_t n) : d_n(n), d_opt(new OptStruct[n]) { d_opt[n - 1] = OptStruct{0, }; } bobcat-3.19.01/iuo/destructor.f0000644000175000017500000000010212223023055015227 0ustar frankfrankinline OptStructArray::~OptStructArray() { delete [] d_opt; } bobcat-3.19.01/iuo/iuo0000644000175000017500000000066612223023055013420 0ustar frankfrank#ifndef INCLUDED_BOBCAT_IUO_ #define INCLUDED_BOBCAT_IUO_ #include #include namespace FBB { void deprecated__(bool &called, char const *msg); class OptStructArray { typedef struct option OptStruct; size_t d_n; OptStruct *d_opt; public: OptStructArray(size_t n); ~OptStructArray(); OptStruct *get(); }; #include "destructor.f" #include "get.f" } // FBB #endif bobcat-3.19.01/iuo/get.f0000644000175000017500000000011612223023055013615 0ustar frankfrankinline OptStructArray::OptStruct *OptStructArray::get() { return d_opt; } bobcat-3.19.01/iuo/iuo.ih0000644000175000017500000000011712222576534014024 0ustar frankfrank#include "iuo" #include using namespace std; using namespace FBB; bobcat-3.19.01/iuo/deprecated.cc0000644000175000017500000000046612222576534015324 0ustar frankfrank#include "iuo.ih" namespace FBB { void deprecated__(bool &called, char const *msg) { if (called) return; cerr << "[Warning] " << msg << " is deprecated.\n" "Avoid its use, see the man-page for alternatives.\n"; called = true; } } bobcat-3.19.01/lc/0000755000175000017500000000000012222576540012506 5ustar frankfrankbobcat-3.19.01/lc/driver/0000755000175000017500000000000012222576540014001 5ustar frankfrankbobcat-3.19.01/lc/driver/build0000755000175000017500000000004612222576540015026 0ustar frankfrank#!/bin/sh g++ -o driver driver.cc -s bobcat-3.19.01/lc/driver/driver.cc0000644000175000017500000000174612222576540015613 0ustar frankfrank#include #include #include #include #include #include using namespace std; using namespace FBB; class Strings { typedef LC lc; vector d_vs; public: Strings() { d_vs.push_back("one"); d_vs.push_back("two"); d_vs.push_back(""); d_vs.push_back("three"); } void display(ostream &out) const { lc c(1, out); find_if(d_vs.begin(), d_vs.end(), FnWrap1c (&Strings::untilEmpty, c)); } private: static bool untilEmpty(string const &str, lc &c) { if (str.empty()) return true; // stop c.f2 << c.f1++ << " " << str << endl; return false; // don't stop } }; int main() { Strings s; s.display(cout); } bobcat-3.19.01/lc/lcgen/0000755000175000017500000000000012222576540013576 5ustar frankfrankbobcat-3.19.01/lc/lcgen/main.cc0000644000175000017500000000227712222576540015041 0ustar frankfrank#include "main.ih" int main(int argc, char **argv) try { // Arg &arg = Arg::initialize("hv", argc, argv); // arg.versionHelp(usage, Icmbuild::version, 1); // // size_t nTypes = A2x(argv[1]); // // if (nTypes <= 2) // { // cerr << "bobcat/lc will accept max. 3 rather than " << nTypes << // "types\n"; // nTypes = 3; // } // // ofstream outf; // if (arg.nArgs() > 1) // Msg::open(outf, arg[1]); // // ostream out(arg.nArgs() == 1 ? cout.rdbuf() : outf.rdbuf()); // OFoldStream fold(out, 0, 79); // // header(fold); // write the header up to/including // // struct Unspecified // // lcBase(fold, nTypes); // define the LCBase struct and // // constructors // // lc(fold, nTypes); // define the LC struct and constructors // // fold << "} // FBB\n" // end the header file (namespace and // "\n" // and include guard) // "#endif\n"; // } catch (Errno const &err) { cout << err.why() << endl; return 1; } catch (...) { return 1; } bobcat-3.19.01/lc/lcgen/list.cc0000644000175000017500000000026312222576540015061 0ustar frankfrank#include "main.ih" void list(ostream &out, size_t nTs, char const *txt) { for (size_t idx = 1; idx < nTs; ++idx) out << txt << idx << ", "; out << txt << nTs; } bobcat-3.19.01/lc/lcgen/usage.cc0000644000175000017500000000167312222576540015220 0ustar frankfrank// usage.cc #include "main.ih" void usage(std::string const &progname) { cout << "\n" << progname << " by " << Icmbuild::author << "\n" << progname << " V" << Icmbuild::version << " " << Icmbuild::year << "\n" "\n" "Usage: " << progname << " [options] npar [outfile]\n" "Where:\n" " [options] - optional arguments (short options between parentheses):\n" " --help (-h) - provide this help\n" " --version (-v) - show version information and terminate\n" " npar - the max. number of parameters that can be used when\n" " defining a local context.\n" " outfile - file to write the local context to (by default " "stdout)\n" << progname << " generates bobcat/lc, the header file defining the local\n" " context struct (struct FBB::LC) generating templates\n" << endl; } bobcat-3.19.01/lc/lcgen/lcbasecons.cc0000644000175000017500000000207112222576540016221 0ustar frankfrank#include "main.ih" // Define constructor: // 4 (on entry into this function) // gen: // inline LCBase(T1 t1, T2 t2, T3 t3) // 12 // : // 4 // LCBase(t1, t2), // 8 12 // f3(t3) // 8 // {} // 4 void lcBaseCons(std::ostream &out, size_t nargs, size_t argsTot) { out << "inline LCBase" << lm(12); parList(out, nargs); out << '\n' << lm(4); out << ":\n" << lm(8); if (nargs > 2) { out << "LCBase" << flush << lm(12); typeList(out, nargs - 1, argsTot - (nargs - 1)); out << '\n'; argList(out, nargs - 1); out << ",\n" << lm(8); } else out << "f1(t1),\n"; out << "f" << nargs << "(t" << nargs << ")\n" << lm(4) << "{}\n"; } bobcat-3.19.01/lc/lcgen/header.cc0000644000175000017500000000153512222576540015341 0ustar frankfrank#include "main.ih" void header(ostream &out) { out << "#ifndef INCLUDED_BOBCAT_LC_\n" "#define INCLUDED_BOBCAT_LC_\n" "\n" "// This header file was generated by the bobcatlcgen program which is\n" "// distributed with the Bobcat source archive under the directory\n" "// 'bobcat/lc/lcgen'. The binary program itself is probably available as\n" "// /usr/bin/bobcatlcgen.\n" "// The distributed Local Context header allows for the definition and\n" "// declaration of a local context struct having at most 10 fields. If\n" "// more fields are required (e.g., 15), then generate your own local\n" "// context struct header file using the command:\n" "//\n" "// bobcatlcgen 15 your-header\n" "//\n" "// and #include \"your-header\" rather than in your sources.\n" "\n" "namespace FBB\n" "{\n" "\n" "struct Unspecified\n" "{};\n" "\n"; } bobcat-3.19.01/lc/lcgen/typedeflist.cc0000644000175000017500000000020612222576540016437 0ustar frankfrank#include "main.ih" void typeDefList(ostream &out, size_t nTs) { out << '<'; list(out, nTs, "typename T"); out << '>'; } bobcat-3.19.01/lc/lcgen/lc.cc0000644000175000017500000000141112222576540014500 0ustar frankfrank#include "main.ih" // Define: (lmargin values under the lines) // // template // 0 4 // struct LC: public LCBase // 0 12 // { // 0 // lcCons() // }; // 0 void lc(ostream &out, size_t nargs) { out << "template " << lm(4); typeDefList(out, nargs, 2, " = Unspecified"); out << "\n" << lm(0) << "struct LC: public LCBase" << lm(12); typeList(out, nargs, 0); out << "\n" << lm(0) << "{\n"; for (size_t idx = nargs; idx >= 2; --idx) lcCons(out, idx, nargs); out << lm(0) << "};\n" "\n"; } bobcat-3.19.01/lc/lcgen/typelist.cc0000644000175000017500000000034012222576540015757 0ustar frankfrank#include "main.ih" void typeList(ostream &out, size_t nTs, size_t nUnspec) { out << '<'; list(out, nTs, "T"); if (nUnspec) { out << ", "; listUnspec(out, nUnspec); } out << '>'; } bobcat-3.19.01/lc/lcgen/typedeflist2.cc0000644000175000017500000000064512222576540016530 0ustar frankfrank#include "main.ih" void typeDefList(ostream &out, size_t nArgs, size_t nNoDefault, char const *defaultType) { out << '<'; list(out, nNoDefault, "typename T"); out << ", "; for (size_t idx = nNoDefault + 1; idx < nArgs; ++idx) out << "typename T" << idx << defaultType << ", "; out << "typename T" << nArgs << defaultType << '>'; } bobcat-3.19.01/lc/lcgen/parlist.cc0000644000175000017500000000033612222576540015565 0ustar frankfrank#include "main.ih" void parList(ostream &out, size_t nTs) { out << '('; for (size_t idx = 1; idx < nTs; ++idx) out << "T" << idx << " t" << idx << ", "; out << "T" << nTs << " t" << nTs << ")"; } bobcat-3.19.01/lc/lcgen/version.cc0000644000175000017500000000031412222576540015570 0ustar frankfrank// version.cc #include "main.ih" namespace Icmbuild { char version[] = "0.10"; char year[] = "2009"; char author[] = "Frank B. Brokken (f.b.brokken@rug.nl)"; } bobcat-3.19.01/lc/lcgen/main.ih0000644000175000017500000000214412222576540015045 0ustar frankfrank#include #include #include #include #include #include #include #include #include namespace Icmbuild { extern char version[]; extern char year[]; extern char author[]; }; void usage(std::string const &progname); void header(std::ostream &out); void lcBase(std::ostream &out, size_t nargs); void typeList(std::ostream &out, size_t nTs, size_t nUnspec); void typeDefList(std::ostream &out, size_t nTs); void typeDefList(std::ostream &out, size_t nArgs, size_t nNoDefault, char const *defaultType); void list(std::ostream &out, size_t nTs, char const *txt); void listUnspec(std::ostream &out, size_t nUnspec); void argList(std::ostream &out, size_t nTs); void parList(std::ostream &out, size_t nTs); void lcBaseCons(std::ostream &out, size_t nargs, size_t nArgsTotal); void lcCons(std::ostream &out, size_t nargs, size_t argsTot); void lc(std::ostream &out, size_t nargs); using namespace Icmbuild; using namespace std; using namespace FBB; bobcat-3.19.01/lc/lcgen/listunspec.cc0000644000175000017500000000026112222576540016275 0ustar frankfrank#include "main.ih" void listUnspec(ostream &out, size_t nUnspec) { for (size_t idx = 1; idx < nUnspec; ++idx) out << "Unspecified, "; out << "Unspecified"; } bobcat-3.19.01/lc/lcgen/lccons.cc0000644000175000017500000000122712222576540015370 0ustar frankfrank#include "main.ih" // 0 (from lc.cc) // // inline LC(T1 t1, T2 t2, T3 t3) // 4 12 // : // LCBase(t1, t2, t3) // 8 12 // {} // 4 void lcCons(std::ostream &out, size_t nargs, size_t argsTot) { out << lm(4) << "inline LC" << flush << lm(12); parList(out, nargs); out << "\n" << lm(4) << ":\n" << lm(8) << "LCBase" << flush << lm(12); typeList(out, nargs, argsTot - nargs); argList(out, nargs); out << "\n" << lm(4) << "{}\n" "\n"; } bobcat-3.19.01/lc/lcgen/arglist.cc0000644000175000017500000000017112222576540015551 0ustar frankfrank#include "main.ih" void argList(ostream &out, size_t nTs) { out << '('; list(out, nTs, "t"); out << ')'; } bobcat-3.19.01/lc/lcgen/lcbase.cc0000644000175000017500000000357412222576540015347 0ustar frankfrank#include "main.ih" void lcBase(ostream &out, size_t nargs) { for (size_t idx = nargs; idx >= 2; --idx) { // Define (nrs below line indicate lmargin settings): // template // 4 // struct LCBase: public LCBase // 0 12 // { // 0 out << "template " << lm(4); typeDefList(out, idx); out << "\n" << lm(0) << "struct LCBase"; if (idx == 2) // the final specialization typeList(out, idx, nargs - idx); else // the other specializations { if (idx == nargs) // all but the first struct starts out << ": "; // on a new line. else { // the 2nd, 3rd: specializations out << lm(12); typeList(out, idx, nargs - idx); out << ':' << lm(4) << '\n'; } // inherit from the next special. out << "public LCBase" << lm(12); typeList(out, idx - 1, nargs - (idx - 1)); } out << lm(0) << "\n" "{\n" << lm(4); // Define variable(s): and constructor: // T3 f3; // 4 if (idx == 2) out << "T1 f1;\n"; out << "T" << idx << " f" << idx << ";\n" "\n"; lcBaseCons(out, idx, nargs); // define the constructor out << lm(0) << "};\n" // end the LCBase class "\n"; } } bobcat-3.19.01/lc/lc0000644000175000017500000001644412222576540013040 0ustar frankfrank#ifndef INCLUDED_BOBCAT_LC_ #define INCLUDED_BOBCAT_LC_ // This header file was generated by the bobcatlcgen program which is // distributed with the Bobcat source archive under the directory // 'bobcat/lc/lcgen'. The binary program itself is probably available as // /usr/bin/bobcatlcgen. // The distributed Local Context header allows for the definition and // declaration of a local context struct having at most 10 fields. If // more fields are required (e.g., 15), then generate your own local // context struct header file using the command: // // bobcatlcgen 15 your-header // // and #include "your-header" rather than in your sources. namespace FBB { struct Unspecified {}; template struct LCBase: public LCBase { T10 f10; inline LCBase(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) : LCBase (t1, t2, t3, t4, t5, t6, t7, t8, t9), f10(t10) {} }; template struct LCBase: public LCBase { T9 f9; inline LCBase(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) : LCBase (t1, t2, t3, t4, t5, t6, t7, t8), f9(t9) {} }; template struct LCBase: public LCBase { T8 f8; inline LCBase(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) : LCBase (t1, t2, t3, t4, t5, t6, t7), f8(t8) {} }; template struct LCBase: public LCBase { T7 f7; inline LCBase(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) : LCBase (t1, t2, t3, t4, t5, t6), f7(t7) {} }; template struct LCBase: public LCBase { T6 f6; inline LCBase(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) : LCBase (t1, t2, t3, t4, t5), f6(t6) {} }; template struct LCBase: public LCBase { T5 f5; inline LCBase(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) : LCBase (t1, t2, t3, t4), f5(t5) {} }; template struct LCBase: public LCBase { T4 f4; inline LCBase(T1 t1, T2 t2, T3 t3, T4 t4) : LCBase (t1, t2, t3), f4(t4) {} }; template struct LCBase: public LCBase { T3 f3; inline LCBase(T1 t1, T2 t2, T3 t3) : LCBase (t1, t2), f3(t3) {} }; template struct LCBase { T1 f1; T2 f2; inline LCBase(T1 t1, T2 t2) : f1(t1), f2(t2) {} }; template struct LC: public LCBase { inline LC(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) : LCBase(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) {} inline LC(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) : LCBase(t1, t2, t3, t4, t5, t6, t7, t8, t9) {} inline LC(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) : LCBase(t1, t2, t3, t4, t5, t6, t7, t8) {} inline LC(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) : LCBase(t1, t2, t3, t4, t5, t6, t7) {} inline LC(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) : LCBase(t1, t2, t3, t4, t5, t6) {} inline LC(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) : LCBase(t1, t2, t3, t4, t5) {} inline LC(T1 t1, T2 t2, T3 t3, T4 t4) : LCBase(t1, t2, t3, t4) {} inline LC(T1 t1, T2 t2, T3 t3) : LCBase(t1, t2, t3) {} inline LC(T1 t1, T2 t2) : LCBase(t1, t2) {} }; } // FBB #endif bobcat-3.19.01/level/0000755000175000017500000000000012242431634013213 5ustar frankfrankbobcat-3.19.01/level/operatorinsert.cc0000644000175000017500000000054112222576537016614 0ustar frankfrank#include "level.ih" namespace FBB { std::ostream &operator<<(std::ostream &str, level const &lv) { Log *lp = dynamic_cast(&str); // a Log object is required. return !lp ? // if not, ignore the manip. str : lv.insertInto(str, *lp); } } // FBB bobcat-3.19.01/level/level.ih0000644000175000017500000000012312222576537014652 0ustar frankfrank#include "level" #include using namespace std; using namespace FBB; bobcat-3.19.01/level/driver/0000755000175000017500000000000012222576537014520 5ustar frankfrankbobcat-3.19.01/level/driver/build0000755000175000017500000003704512222576537015556 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/driver // script generated by the C++ icmake script version 2.17b /* Configurable defines: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BISON_FLAGS: This directive is only used when a grammar is generated using bison++. It defines the set of flags that are given to bison++ when bison++ generates the parser. By default the following flags are specified: -v -l The -d and -o flags are always provided (not configurable) BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (by default it is defined to the name of the program to be created). COMPILER: The compiler to use. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) GRAMMAR_LINES: When this directive is defined, #line directives will be generated at the first C++ compound statement in each individual grammar specification file. Undefine if no such #line directives are required. LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM "driver" #define COMPILER "g++-4.0" #define COPT "-Wall -I../../tmp" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "../../tmp/lib" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current, // contains name of current dir. programname; // the name of the program to create int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); #ifdef GRAMMAR_LINES system("./grambuild lines"); #else system("./grambuild"); #endif chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { #ifdef BISON_FLAGS exec("bison++", BISON_FLAGS, "-d", "-o", "parser.cc", "grammar"); #else exec("bison++", "-d", "-o", "parser.cc", "grammar"); #endif } chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || ( exists("../parser/parser.h") && "../parser/parser.h" younger "yylex.cc" ) ) ) exec("flex", interactive, "lexer"); chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; programname = BUILD_PROGRAM; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD if (exists("parser")) // subdir parser exists { CLASSES += "parser "; parser(); } if (exists("scanner")) // subdir scanner exists { CLASSES += "scanner "; scanner(); } #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library) { printf("\n"); exec(COMPILER, "-o", programname, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", programname, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "driver.cc", // program source "driver" // static program library ); #else cpp_make ( "", "driver" // static- or so-library ); #endif } bobcat-3.19.01/level/driver/driver.cc0000644000175000017500000000163512222576537016327 0ustar frankfrank/* driver.cc */ #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { try { Log::getInstance() << "hello world" << endl; } catch(Errno const &e) { cout << e.why() << endl; } Log log(STATIC); log << ": message to cout" << nl << "<-- No timestamp here " << '\n' << "<-- But timestamp here " << endl; Log::getInstance() << "\n"; log.setLevel(1); log.setTimestamp(NOTIMESTAMPS); log.level(0) << "Not shown" << "\n"; log.level(1) << "Shown" << "\n"; log << "This one too" << endl; log << level(0) << "Again not shown\n"; log << level(1) << "Shown again\n"; log.setLevel(5); log << level(1) << "Not shown\n"; log << level(5) << "Shown again\n"; return 0; } bobcat-3.19.01/level/level.f0000644000175000017500000000007012223023055014457 0ustar frankfrankinline level::level(size_t lvel) : d_level(lvel) {} bobcat-3.19.01/level/insertinto.cc0000644000175000017500000000101212222576537015724 0ustar frankfrank#include "level.ih" std::ostream &level::insertInto(ostream &str, Log &lp) const { LogBuffer *lb = dynamic_cast(lp.rdbuf()); return !lb->empty() ? // the object's message buffer // must be empty. str // if not, ignore the // manipulator : lp.level(d_level); // otherwise set the level. } bobcat-3.19.01/level/level0000644000175000017500000000065712223023055014246 0ustar frankfrank#ifndef INCLUDED_BOBCAT_LEVEL_ #define INCLUDED_BOBCAT_LEVEL_ #include namespace FBB { class level; } namespace FBB { class level { friend std::ostream &operator<<(std::ostream &, level const &); size_t d_level; public: explicit level(size_t lvel); private: std::ostream &insertInto(std::ostream &str, Log &lp) const; }; #include "level.f" } // FBB #endif bobcat-3.19.01/localclientsocket/0000755000175000017500000000000012242431634015606 5ustar frankfrankbobcat-3.19.01/localclientsocket/localclientsocket0000644000175000017500000000142512222576523021242 0ustar frankfrank#ifndef INCLUDED_BOBCAT_LOCALCLIENTSOCKET_ #define INCLUDED_BOBCAT_LOCALCLIENTSOCKET_ #include #include #include #include namespace FBB { class LocalClientSocket: public LocalSocketBase { public: LocalClientSocket() = default; explicit LocalClientSocket(std::string const &name); void open(std::string const &name); int connect(); // returns fd (socket) to talk to the server private: LocalClientSocket(LocalClientSocket const &other) = delete; }; inline LocalClientSocket::LocalClientSocket(std::string const &name) : LocalSocketBase(name) {} inline void LocalClientSocket::open(std::string const &name) { LocalSocketBase::open(name); } } // FBB #endif bobcat-3.19.01/localclientsocket/connect.cc0000644000175000017500000000034712222576523017557 0ustar frankfrank#include "localclientsocket.ih" int LocalClientSocket::connect() { if (::connect(socket(), sockaddrPtr(), size()) < 0) throw Exception() << "LocalClientSocket::connect(): " << errnodescr; return socket(); } bobcat-3.19.01/localclientsocket/localclientsocket.ih0000644000175000017500000000024412222576523021637 0ustar frankfrank#include "localclientsocket" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/localclientsocket/driver/0000755000175000017500000000000012222576523017106 5ustar frankfrankbobcat-3.19.01/localclientsocket/driver/build0000755000175000017500000003074012222576523020137 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/client // script generated by the C++ icmake script version 1.61 /* Configurable defines for the build script: BISON++: only to be defined if bison++ is to be used in the subdirectory 'parser' on the file 'grammar', generating 'parser.cc' and 'parser.h' in that directory. FLEX++: only to be defined if flex++ is to be used in the subdirectory 'scanner' on the file 'yylex', generating 'yylex.cc' CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ //#define BISON++ //#define FLEX++ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* COMPILER: "g++" for C++ sources. Do not change this, unless you're sure you want something else. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking USE_LIBRARY: define this if you want a library for the object modules. Undefined by default: so NO LIBRARY IS USED. PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed. (default: defined) RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //Do not change the next define unless you know what you're doing: #define COMPILER "g++" // COPT: the set of C-options #define COPT "-Wall" #define ECHO_REQUEST ON // #define GDB // Extra libraries required. Remove lib and .a from the library names. // E.g., #define LIBS "m Xt" to link libm.a and libXt.a explicitly // Specify libs from the most specific to the most general one. #define LIBS "bobcat" // Extra library-paths required. // E.g., #define LIBPATH "/some/path /some/other/path" to search these paths // apart from the default paths #define LIBPATH "" // uncomment if you WANT to use a library // #define USE_LIBRARY #define PROGRAM #define RELINK // DO NOT ALTER THINGS BELOW THIS LINE string // contain options for libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, lopt, libxxxa; // expanded lib-name int relink; // internally used: != 0 to relink string ofiles, // wildcards for o-files sources, // sources to be used wild, // wildcard of extension current; // contains name of current dir. /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list #ifdef USE_LIBRARY objfile = change_ext(file, "o"); // make obj-filename #else objfile = "./o/" + change_ext(file, "o"); // make obj-filename #endif if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* parser.im */ void parser() { chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); } /* scanner.im */ void scanner() { chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", #ifdef INTERACTIVE "-I", #endif "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef USE_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { #ifndef RELINK if ( relink // new library, new main.obj || !exists(exe) // final program doesn't exist ) #endif { printf("\n"); exec(COMPILER, "-o", exe, #ifdef USE_LIBRARY "-l" + library, #else ofiles, #endif libs, "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; #ifndef USE_LIBRARY if (!exists("o")) system("mkdir o"); #endif if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) { #ifdef USE_LIBRARY exec(COMPILER, "-c " COPT + " " + copt + " " + nextfile); #else exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o") + " " COPT + " " + copt + " " + nextfile); #endif } relink = 1; printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { list arlist, objlist; string to, from; objlist = makelist("*.o"); if (!sizeof(objlist)) return; printf("\n"); relink = 1; exec("ar", "rvs", library, "*.o"); exec("rm", "*.o"); printf("\n"); } void prefix_class(string class_id) { list o_files; string o_file; int i; o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(wild, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix, .a suffix if main is given here, libmain.a is created) string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int n, index; list classes; string cwd; #ifdef BISON++ CLASSES += "parser "; if (exists("parser")) // subdir parser exists parser(); #endif #ifdef FLEX++ CLASSES += "scanner "; if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes cwd = chdir("."); ofiles = "o/*.o"; // std set of o-files classes = strtok(CLASSES, " "); // list of classes if (n = sizeof(classes)) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use wild = sources; // make library name libxxxa = chdir(".") + "lib" + library + ".a"; // first process all classes for (index = 0; index < n; index++) { current = element(index, classes); // next class to process chdir(current); // change to directory current = "subdir " + current; std_cpp (libxxxa); // compile all files chdir( cwd); // go back to parent dir } current = "auxiliary " + wild + " files"; std_cpp (libxxxa); // compile all files in current dir for (index = 0; index < n; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. #ifdef USE_LIBRARY prefix_class((string)index); // prefix class-number for .o files updatelib(libxxxa); #endif chdir(cwd); // go back to parent dir } current = ""; // no class anymore #ifdef USE_LIBRARY updatelib(libxxxa); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); } void main() { echo(ECHO_REQUEST); sources = "*.cc"; setlibs(); #ifdef GDB copt = "-g"; #endif #ifdef PROGRAM cpp_make ( "client.cc", // program source "client", // program library "client" // binary program ); #else cpp_make ( "", "client", // program library "" ); #endif } bobcat-3.19.01/localclientsocket/driver/client.cc0000644000175000017500000000243112222576523020673 0ustar frankfrank#include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) { cerr << "Provide filename representing the unix domain socket\n"; return 1; } LocalClientSocket client(argv[1]); int fd = client.connect(); string line; cout << "Connecting to socket " << fd << endl; IFdStream in(fd); // stream to read from OFdStream out(fd); // stream to write to while (true) { // Ask for a textline, stop if empty / none cout << "? "; if (!getline(cin, line) || line.length() == 0) return 0; cout << "Line read: " << line << endl; // Return the line to the server out << line.c_str() << endl; cout << "wrote line\n"; // Wait for a reply from the server getline(in, line); cout << "Answer: " << line << endl; } return 0; } catch (Errno const &err) { cerr << err.why() << "\n" << "Can't connect to " << argv[1] << ", port " << argv[2] << endl; return 1; } bobcat-3.19.01/localserversocket/0000755000175000017500000000000012242431634015636 5ustar frankfrankbobcat-3.19.01/localserversocket/localserversocket.ih0000644000175000017500000000027412222576533021723 0ustar frankfrank#include "localserversocket" #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/localserversocket/destructor.cc0000644000175000017500000000022412222576533020347 0ustar frankfrank#include "localserversocket.ih" LocalServerSocket::~LocalServerSocket() { if (d_unlink) unlink(d_name.c_str()); } bobcat-3.19.01/localserversocket/localserversocket1.f0000644000175000017500000000023412223023055021610 0ustar frankfrankinline LocalServerSocket::LocalServerSocket(std::string const &name, Socket action) { open(name, action); } bobcat-3.19.01/localserversocket/localserversocket0000644000175000017500000000151012224261737021315 0ustar frankfrank#ifndef INCLUDED_BOBCAT_LOCALSERVERSOCKET_ #define INCLUDED_BOBCAT_LOCALSERVERSOCKET_ #include #include namespace FBB { class LocalServerSocket: public LocalSocketBase { bool d_unlink; std::string d_name; public: enum Socket { KEEP, UNLINK, }; LocalServerSocket() = default; explicit LocalServerSocket(std::string const &name, // 1.f Socket action = KEEP); ~LocalServerSocket(); void open(std::string const &name, Socket action = KEEP); void listen(size_t backlog = 5, bool blocking = true); size_t accept(); private: LocalServerSocket(LocalServerSocket const &other) = delete; }; #include "localserversocket1.f" } // FBB #endif bobcat-3.19.01/localserversocket/open.cc0000644000175000017500000000062712222576533017121 0ustar frankfrank#include "localserversocket.ih" void LocalServerSocket::open(string const &name, Socket action) { LocalSocketBase::open(name); d_unlink = action == UNLINK; d_name = name; if (bind(socket(), sockaddrPtr(), size()) < 0) throw Exception() << "LocalServerSocket::open(" << name << "): " << errnodescr; } bobcat-3.19.01/localserversocket/accept.cc0000644000175000017500000000066012222576533017414 0ustar frankfrank#include "localserversocket.ih" size_t LocalServerSocket::accept() { sockaddr_un address; socklen_t size = sizeof(address); int sock = ::accept ( socket(), reinterpret_cast(&address), &size ); if (sock < 0) throw Exception() << "LocalServerSocket::accept(): " << errnodescr; return sock; } bobcat-3.19.01/localserversocket/driver/0000755000175000017500000000000012222576533017137 5ustar frankfrankbobcat-3.19.01/localserversocket/driver/build0000755000175000017500000003101712222576533020166 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/server // script generated by the C++ icmake script version 1.61 /* Configurable defines for the build script: BISON++: only to be defined if bison++ is to be used in the subdirectory 'parser' on the file 'grammar', generating 'parser.cc' and 'parser.h' in that directory. FLEX++: only to be defined if flex++ is to be used in the subdirectory 'scanner' on the file 'yylex', generating 'yylex.cc' CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ //#define BISON++ //#define FLEX++ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* COMPILER: "g++" for C++ sources. Do not change this, unless you're sure you want something else. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking USE_LIBRARY: define this if you want a library for the object modules. Undefined by default: so NO LIBRARY IS USED. PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed. (default: defined) RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //Do not change the next define unless you know what you're doing: #define COMPILER "g++" // COPT: the set of C-options #define COPT "-Wall" #define ECHO_REQUEST ON // #define GDB // Extra libraries required. Remove lib and .a from the library names. // E.g., #define LIBS "m Xt" to link libm.a and libXt.a explicitly // Specify libs from the most specific to the most general one. #define LIBS "bobcat" // Extra library-paths required. // E.g., #define LIBPATH "/some/path /some/other/path" to search these paths // apart from the default paths #define LIBPATH "" // uncomment if you WANT to use a library // #define USE_LIBRARY #define PROGRAM #define RELINK // DO NOT ALTER THINGS BELOW THIS LINE string // contain options for libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, lopt, libxxxa; // expanded lib-name int relink; // internally used: != 0 to relink string ofiles, // wildcards for o-files sources, // sources to be used wild, // wildcard of extension current; // contains name of current dir. /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list #ifdef USE_LIBRARY objfile = change_ext(file, "o"); // make obj-filename #else objfile = "./o/" + change_ext(file, "o"); // make obj-filename #endif if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* parser.im */ void parser() { chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); } /* scanner.im */ void scanner() { chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", #ifdef INTERACTIVE "-I", #endif "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef USE_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { #ifndef RELINK if ( relink // new library, new main.obj || !exists(exe) // final program doesn't exist ) #endif { printf("\n"); exec(COMPILER, "-o", exe, #ifdef USE_LIBRARY "-l" + library, #else ofiles, #endif libs, "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; #ifndef USE_LIBRARY if (!exists("o")) system("mkdir o"); #endif if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) { #ifdef USE_LIBRARY exec(COMPILER, "-c " COPT + " " + copt + " " + nextfile); #else exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o") + " " COPT + " " + copt + " " + nextfile); #endif } relink = 1; printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { list arlist, objlist; string to, from; objlist = makelist("*.o"); if (!sizeof(objlist)) return; printf("\n"); relink = 1; exec("ar", "rvs", library, "*.o"); exec("rm", "*.o"); printf("\n"); } void prefix_class(string class_id) { list o_files; string o_file; int i; o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(wild, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix, .a suffix if main is given here, libmain.a is created) string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int n, index; list classes; string cwd; #ifdef BISON++ CLASSES += "parser "; if (exists("parser")) // subdir parser exists parser(); #endif #ifdef FLEX++ CLASSES += "scanner "; if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes cwd = chdir("."); ofiles = "o/*.o"; // std set of o-files classes = strtok(CLASSES, " "); // list of classes if (n = sizeof(classes)) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use wild = sources; // make library name libxxxa = chdir(".") + "lib" + library + ".a"; // first process all classes for (index = 0; index < n; index++) { current = element(index, classes); // next class to process chdir(current); // change to directory current = "subdir " + current; std_cpp (libxxxa); // compile all files chdir( cwd); // go back to parent dir } current = "auxiliary " + wild + " files"; std_cpp (libxxxa); // compile all files in current dir for (index = 0; index < n; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. #ifdef USE_LIBRARY prefix_class((string)index); // prefix class-number for .o files updatelib(libxxxa); #endif chdir(cwd); // go back to parent dir } current = ""; // no class anymore #ifdef USE_LIBRARY updatelib(libxxxa); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); #ifdef FLEX++ libs += " -lfl"; #endif cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); } void main() { echo(ECHO_REQUEST); sources = "*.cc"; setlibs(); #ifdef GDB copt = "-g"; #endif #ifdef PROGRAM cpp_make ( "server.cc", // program source "server", // program library "server" // binary program ); #else cpp_make ( "", "server", // program library "" ); #endif } bobcat-3.19.01/localserversocket/driver/server.cc0000644000175000017500000000256512222576533020764 0ustar frankfrank#include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) { cerr << "Provide local filename, e.g., /tmp/uds\n"; return 1; } LocalServerSocket server(argv[1]); cerr << "server using `" << argv[1] << "'" << endl; cout << "The server terminates when it receives a single `q' on a line\n" "A connection is terminated when no input is received anymore.\n" "Then another connection is possible" << endl; server.listen(); // listen in blocking mode while (true) { int fd = server.accept(); cerr << "Client FD = " << fd << ", " << endl; IFdStream in(fd); // stream to read from client OFdStream out(fd); // stream to write to client string cmd; while (getline(in, cmd)) { cout << "Got: " << cmd << endl; out << "Got: " << cmd << "\r" << endl; if (cmd[0] == 'q') return 0; } cout << "Ready for another connection\n"; } } catch (Errno const &err) { cerr << err.why() << endl << "Server socket on port " << argv[1] << " can't be opened" << endl; return -1; } bobcat-3.19.01/localserversocket/listen.cc0000644000175000017500000000105312222576533017450 0ustar frankfrank#include "localserversocket.ih" void LocalServerSocket::listen(size_t backlog, bool blocking) { static char name[] = "LocalServerSocket::listen(): "; if (::listen(socket(), backlog) < 0) throw Exception() << name << errnodescr; if (blocking) return; if // not tested ( fcntl ( socket(), F_SETFL, fcntl(socket(), F_GETFL, 0) | O_NONBLOCK ) == -1 ) throw Exception() << name << errnodescr; } bobcat-3.19.01/localsocketbase/0000755000175000017500000000000012242431634015242 5ustar frankfrankbobcat-3.19.01/localsocketbase/sockaddrptr.f0000644000175000017500000000017312223023055017723 0ustar frankfrankinline sockaddr const *LocalSocketBase::sockaddrPtr() const { return reinterpret_cast(&d_address); } bobcat-3.19.01/localsocketbase/size.f0000644000175000017500000000010512223023055016350 0ustar frankfrankinline size_t LocalSocketBase::size() const { return d_length; } bobcat-3.19.01/localsocketbase/localsocketbase.ih0000644000175000017500000000021712222576537020734 0ustar frankfrank#include "localsocketbase" #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/localsocketbase/socket.f0000644000175000017500000000010412223023055016665 0ustar frankfrankinline int LocalSocketBase::socket() const { return d_socket; } bobcat-3.19.01/localsocketbase/open.cc0000644000175000017500000000125412222576537016526 0ustar frankfrank#include "localsocketbase.ih" void LocalSocketBase::open(std::string const &name) { d_address.sun_family = AF_UNIX; if (name.length() >= sizeof(d_address.sun_path)) throw Exception() << "LocalSocketBase::open(" << name << "): " << errnodescr; d_address.sun_path[name.copy(d_address.sun_path, string::npos)] = 0; d_length = sizeof(d_address.sun_family) + name.length(); d_socket = ::socket(AF_UNIX, SOCK_STREAM, 0); if (d_socket < 0) throw Exception() << "LocalSocketBase::open(" << name << "): " << errnodescr; } bobcat-3.19.01/localsocketbase/localsocketbase0000644000175000017500000000146112224231211020312 0ustar frankfrank#ifndef INCLUDED_BOBCAT_LOCALSOCKETBASE_ #define INCLUDED_BOBCAT_LOCALSOCKETBASE_ #include #include #include namespace FBB { class LocalSocketBase { size_t d_length; int d_socket; struct sockaddr_un d_address; protected: LocalSocketBase(); // 1 explicit LocalSocketBase(std::string const &name); // 1.f void open(std::string const &name); int socket() const; // .f size_t size() const; // .f sockaddr const *sockaddrPtr() const; // .f }; #include "localsocketbase1.f" #include "size.f" #include "sockaddrptr.f" #include "socket.f" } // FBB #endif bobcat-3.19.01/localsocketbase/localsocketbase1.f0000644000175000017500000000012512223023055020617 0ustar frankfrankinline LocalSocketBase::LocalSocketBase(std::string const &name) { open(name); } bobcat-3.19.01/localsocketbase/localsocketbase1.cc0000644000175000017500000000024112222576537020777 0ustar frankfrank#include "localsocketbase.ih" LocalSocketBase::LocalSocketBase() : d_length(0), d_socket(-1) { memset(&d_address, 0, sizeof(struct sockaddr_un)); } bobcat-3.19.01/log/0000755000175000017500000000000012242431634012665 5ustar frankfrankbobcat-3.19.01/log/operatorinsert.cc0000644000175000017500000000075612222576534016273 0ustar frankfrank#include "log.ih" namespace FBB { std::ostream &operator<<(std::ostream &str, LogManipulator manipulator) { switch (manipulator) { case FATAL: str.flush(); throw Exception(1); case nl: str << static_cast(0); // 0-char is interpreted by // LogBuffer as '\n', without break; // timestamp writing request. } return str; } } // FBB bobcat-3.19.01/log/instance.cc0000644000175000017500000000025712222576534015013 0ustar frankfrank#include "log.ih" Log &Log::instance() { if (!s_stream.get()) throw Exception() << "Log::getInstance(): FBB::Log not initialized"; return *s_stream.get(); } bobcat-3.19.01/log/setlevel.cc0000644000175000017500000000015512222576534015027 0ustar frankfrank#include "log.ih" void Log::setLevel(size_t newLevel) { d_level = newLevel; level(d_activeLevel); } bobcat-3.19.01/log/open.cc0000644000175000017500000000103712222576534014145 0ustar frankfrank#include "log.ih" void Log::open(string const &filename, ios::openmode mode, char const *delim) { if (!filename.length() || filename == "&1") setStream(cout); else if (filename == "&2") setStream(cerr); else { d_stream.open(filename.c_str(), mode); if (!d_stream) Exception() << "Log::Log(string, ...): can't write `" << filename << '\''; setStream(d_stream); } settimestamp(TIMESTAMPS, delim); init(); } bobcat-3.19.01/log/initialize.cc0000644000175000017500000000052512222576534015346 0ustar frankfrank#include "log.ih" Log &Log::initialize(std::string const &filename, std::ios::openmode mode, char const *delim) { if (s_stream.get()) throw Exception() << "Log::getInstance(): FBB::Log already initialized"; s_stream.reset(new Log(filename, mode, delim)); return *s_stream.get(); } bobcat-3.19.01/log/log2.cc0000644000175000017500000000021612222576534014045 0ustar frankfrank#include "log.ih" Log::Log(ostream &out, char const *delim) : LogBuffer(out, TIMESTAMPS, true, delim), ostream(this) { init(); } bobcat-3.19.01/log/driver/0000755000175000017500000000000012222576534014167 5ustar frankfrankbobcat-3.19.01/log/driver/build0000755000175000017500000000005412222576534015213 0ustar frankfrank#!/bin/sh g++ -o driver driver.cc -lbobcat bobcat-3.19.01/log/driver/driver.cc0000644000175000017500000000063312222576534015773 0ustar frankfrank#include #include #include using namespace std; using namespace FBB; int main() { Log &log = Log::initialize("&1"); log << "This message is written to cout" << nl << setw(16) << ' ' << "occupying multiple lines\n"; log.off(); log << "This message is not shown\n"; log.setLevel(0); log << "This message is shown again\n"; return 0; } bobcat-3.19.01/log/data.cc0000644000175000017500000000006212222576534014112 0ustar frankfrank#include "log.ih" unique_ptr Log::s_stream; bobcat-3.19.01/log/log1.cc0000644000175000017500000000017412222576534014047 0ustar frankfrank#include "log.ih" Log::Log(char const *delim) : LogBuffer(TIMESTAMPS, false, delim), ostream(this) { init(); } bobcat-3.19.01/log/log0000644000175000017500000000272712223023055013372 0ustar frankfrank#ifndef INCLUDED_BOBCAT_LOG_ #define INCLUDED_BOBCAT_LOG_ #include #include #include namespace FBB { enum LogManipulator { FATAL, nl, }; class Log: private LogBuffer, public std::ostream { private: static std::unique_ptr s_stream; std::ofstream d_stream; size_t d_level; size_t d_activeLevel; public: static Log &instance(); static Log &initialize(std::string const &filename, std::ios::openmode = std::ios::out | std::ios::app, char const *delim = " "); Log(char const *delim = " "); Log(std::ostream &out, char const *delim = " "); Log(std::string const &filename, std::ios::openmode = std::ios::out | std::ios::app, char const *delim = " "); void open(std::string const &filename, std::ios::openmode = std::ios::out | std::ios::app, char const *delim = " "); size_t level() const; // .f std::ostream &level(size_t useLevel); void setLevel(size_t newLevel); void setTimestamp(TimeStamps timeStamp, char const *delim = " "); void off(); // .f private: void init(); }; #include "level.f" #include "off.f" std::ostream &operator<<(std::ostream &str, LogManipulator); } // FBB #endif bobcat-3.19.01/log/level.cc0000644000175000017500000000023412222576534014311 0ustar frankfrank#include "log.ih" ostream &Log::level(size_t activeLevel) { d_activeLevel = activeLevel; setActive(d_level <= d_activeLevel); return *this; } bobcat-3.19.01/log/level.f0000644000175000017500000000007112223023055014132 0ustar frankfrankinline size_t Log::level() const { return d_level; } bobcat-3.19.01/log/off.f0000644000175000017500000000006212223023055013575 0ustar frankfrankinline void Log::off() { setActive(false); } bobcat-3.19.01/log/settimestamp.cc0000644000175000017500000000016112222576534015720 0ustar frankfrank#include "log.ih" void Log::setTimestamp(TimeStamps type, char const *delim) { settimestamp(type, delim); } bobcat-3.19.01/log/log.ih0000644000175000017500000000022612222576534013777 0ustar frankfrank#include "log" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/log/init.cc0000644000175000017500000000015412222576534014146 0ustar frankfrank#include "log.ih" void Log::init() { d_level = 0; d_activeLevel = numeric_limits::max(); } bobcat-3.19.01/log/log3.cc0000644000175000017500000000023412222576534014046 0ustar frankfrank#include "log.ih" Log::Log(string const &filename, ios::openmode mode, char const *delim) : ostream(this) { open(filename, mode, delim); } bobcat-3.19.01/logbuffer/0000755000175000017500000000000012242431634014057 5ustar frankfrankbobcat-3.19.01/logbuffer/logbuffer0000644000175000017500000000321512223023055015747 0ustar frankfrank#ifndef INCLUDED_BOBCAT_LOGBUFFER_ #define INCLUDED_BOBCAT_LOGBUFFER_ #include #include #include namespace FBB { enum TimeStamps { NOTIMESTAMPS, TIMESTAMPS }; class LogBuffer: public std::streambuf { std::ostream *d_stream; // the stream to insert info to bool d_insertTimestamp; // write the timestamp or not bool d_active; // actually write information or not bool d_empty; // set to true at the beginning, after writing \n std::string d_delim; // delimiter following time stamps public: explicit LogBuffer( // output to cerr TimeStamps timestamps = TIMESTAMPS, bool active = true, char const *delim = " "); explicit LogBuffer(std::ostream &stream, TimeStamps timestamps = TIMESTAMPS, bool active = true, char const *delim = " "); void setStream(std::ostream &stream); // .f bool empty() const; // .f void setActive(bool active); // .f void settimestamp(TimeStamps timestamps, char const *delim = " "); void setEmpty(bool empty); // .f protected: virtual int pSync(); private: virtual int sync(); virtual int overflow(int c); void insertTimestamp(); LogBuffer(LogBuffer const &other) = delete; LogBuffer &operator=(LogBuffer const &other) = delete; }; #include "empty.f" #include "setactive.f" #include "setempty.f" #include "setstream.f" } // FBB #endif bobcat-3.19.01/logbuffer/logbuffer1.cc0000644000175000017500000000076612222576523016440 0ustar frankfrank#include "logbuffer.ih" LogBuffer::LogBuffer(TimeStamps timestamps, bool active, char const *delim) : d_stream(&cerr), d_active(active), d_empty(true) { settimestamp(timestamps, delim); setp(0, 0); // we're not using buffering, so we see every single // character. overflow() may therefore act like a filter, // which decides what to do depending on the booleans. // see overflow() for details. } bobcat-3.19.01/logbuffer/setstream.f0000644000175000017500000000012312223023055016222 0ustar frankfrankinline void LogBuffer::setStream(std::ostream &stream) { d_stream = &stream; } bobcat-3.19.01/logbuffer/setempty.f0000644000175000017500000000010512223023055016065 0ustar frankfrankinline void LogBuffer::setEmpty(bool empty) { d_empty = empty; } bobcat-3.19.01/logbuffer/driver/0000755000175000017500000000000012222576523015357 5ustar frankfrankbobcat-3.19.01/logbuffer/driver/build0000755000175000017500000000005412222576523016403 0ustar frankfrank#!/bin/sh g++ -o driver driver.cc -lbobcat bobcat-3.19.01/logbuffer/driver/driver.cc0000644000175000017500000000046112222576523017162 0ustar frankfrank#include #include #include using namespace std; using namespace FBB; int main() { LogBuffer buffer(cout); ostream log(&buffer); log << "This message is written to cout" << nl << setw(16) << ' ' << "occupying multiple lines\n"; return 0; } bobcat-3.19.01/logbuffer/overflow.cc0000644000175000017500000000167712222576523016251 0ustar frankfrank#include "logbuffer.ih" int LogBuffer::overflow(int c) { if (!d_active) // ignore the char if we're not active. return c; if (c == 0) // newline without timestamp request d_empty = false; if (d_insertTimestamp) // timestamps requested { if (d_empty) // write one if there's nothing on the line { insertTimestamp(); d_empty = false; } } switch (c) { case 0: // write newline, without considering d_empty true c = '\n'; // also see logbuffer/operatorinsert.cc break; case '\n': // at '\n', set d_empty to true. This generates // a timestamp at the next insertion d_empty = true; break; } return d_stream->write(reinterpret_cast(&c), sizeof(char)) ? c : EOF; } bobcat-3.19.01/logbuffer/empty.f0000644000175000017500000000007512223023055015357 0ustar frankfrankinline bool LogBuffer::empty() const { return d_empty; } bobcat-3.19.01/logbuffer/logbuffer2.cc0000644000175000017500000000101112222576523016421 0ustar frankfrank#include "logbuffer.ih" LogBuffer::LogBuffer(ostream &stream, TimeStamps timestamps, bool active, char const *delim) : d_stream(&stream), d_active(active), d_empty(true) { settimestamp(timestamps, delim); setp(0, 0); // we're not using buffering, so we see every single // character. overflow() may therefore act like a filter, // which decides what to do depending on the booleans. // see overflow() for details. } bobcat-3.19.01/logbuffer/inserttimestamp.cc0000644000175000017500000000045212222576523017624 0ustar frankfrank#include "logbuffer.ih" void LogBuffer::insertTimestamp() { time_t curtime = time(0); struct tm *loctime = localtime (&curtime); char buffer[256]; // see time functions example of `info libc' strftime(buffer, 256, "%b %e %T", loctime); *d_stream << buffer << d_delim; } bobcat-3.19.01/logbuffer/settimestamp.cc0000644000175000017500000000030512222576523017110 0ustar frankfrank#include "logbuffer.ih" void LogBuffer::settimestamp(TimeStamps timestamps, char const *delim) { if ((d_insertTimestamp = (timestamps == TIMESTAMPS))) d_delim = !delim ? "" : delim; } bobcat-3.19.01/logbuffer/psync.cc0000644000175000017500000000013112222576523015522 0ustar frankfrank#include "logbuffer.ih" int LogBuffer::pSync() { d_stream->flush(); return 0; } bobcat-3.19.01/logbuffer/logbuffer.ih0000644000175000017500000000021212222576523016354 0ustar frankfrank#include "logbuffer" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/logbuffer/sync.cc0000644000175000017500000000010712222576524015346 0ustar frankfrank#include "logbuffer.ih" int LogBuffer::sync() { return pSync(); } bobcat-3.19.01/logbuffer/setactive.f0000644000175000017500000000011112223023055016177 0ustar frankfrankinline void LogBuffer::setActive(bool active) { d_active = active; } bobcat-3.19.01/mailheaders/0000755000175000017500000000000012242431634014362 5ustar frankfrankbobcat-3.19.01/mailheaders/oparrow.f0000644000175000017500000000015212223052102016204 0ustar frankfrankinline std::string const *MailHeaders::const_hdr_iterator::operator->() const { return &*d_current; } bobcat-3.19.01/mailheaders/oppostinc.f0000644000175000017500000000021712223051520016536 0ustar frankfrankinline MailHeaders::const_hdr_iterator MailHeaders::const_hdr_iterator::operator++(int) { return const_hdr_iterator(d_mh, d_current++); } bobcat-3.19.01/mailheaders/beginh.f0000644000175000017500000000042112223051107015752 0ustar frankfrankinline MailHeaders::const_hdr_iterator MailHeaders::beginh() const { return const_hdr_iterator(this, begin()); // returns iterator over all headers // matching d_hdr by the d_match type } bobcat-3.19.01/mailheaders/size.f0000644000175000017500000000010712223050734015476 0ustar frankfrankinline size_t MailHeaders::size() const { return d_lines.size(); } bobcat-3.19.01/mailheaders/rbegin.f0000644000175000017500000000015012223050611015762 0ustar frankfrankinline MailHeaders::const_reverse_iterator MailHeaders::rbegin() const { return d_lines.rbegin(); } bobcat-3.19.01/mailheaders/setheaderiterator.f0000644000175000017500000000017112223051053020236 0ustar frankfrankinline void MailHeaders::setHeaderIterator(char const *header, Match match) { d_hdr = header; d_match = match; } bobcat-3.19.01/mailheaders/mailheaders0000644000175000017500000001177112226263747016604 0ustar frankfrank#ifndef INCLUDED_BOBCAT__MAILHEADERS_ #define INCLUDED_BOBCAT_MAILHEADERS_ #include #include #include #include namespace FBB { class MailHeaders { public: typedef std::vector::const_iterator const_iterator; typedef std::vector::const_reverse_iterator const_reverse_iterator; enum Mode { DONT_READ, READ }; enum Match { FAIL, INITIAL, PARTIAL, FULL, caseInsensitive, CASE_INITIAL = caseInsensitive, CASE_PARTIAL, CASE_FULL, lastMatch = CASE_FULL }; private: enum Size { SIZEOFMATCH = lastMatch + 1, }; std::vector d_lines; std::istream &d_in; std::string d_hdr; Match d_match; public: class const_hdr_iterator: public std::iterator { friend class MailHeaders; typedef bool(*Comparator)(std::string const &header, std::string const &key); MailHeaders const *d_mh; std::string d_key; Comparator d_comparator; const_iterator d_current; static Comparator s_comparator[]; const_hdr_iterator(MailHeaders const *mailHeaders, const_iterator begin); const_iterator lookup(const_iterator const &old) const; const_iterator lookdown(const_iterator const &old) const; static bool fail(std::string const &hdr, // .f std::string const &key); static bool initial(std::string const &hdr, // .f std::string const &key); static bool partial(std::string const &hdr, // .f std::string const &key); static bool full(std::string const &hdr, // .f std::string const &key); static bool caseInitial(std::string const &hdr, // .f std::string const &key); static bool casePartial(std::string const &hdr, // .f std::string const &key); static bool caseFull(std::string const &hdr, // .f std::string const &key); public: const_hdr_iterator &operator++(); // opinc.f const_hdr_iterator &operator--(); // opdec.f const_hdr_iterator operator++(int); // oppostinc.f // not used, but potentially available in consthdropdec.cc // const_hdr_iterator operator--(int); bool operator==(const_hdr_iterator const &other) // opeq.f const; bool operator!=(const_hdr_iterator const &other) // opneq.f const; std::string const &operator*() const; // opstar.f std::string const *operator->() const; // oparrow.f }; typedef std::reverse_iterator const_reverse_hdr_iterator; explicit MailHeaders(std::istream &in, Mode mode = READ); MailHeaders(MailHeaders &&tmp); MailHeaders &operator=(MailHeaders &&tmp); void read(); void setHeaderIterator(char const *header, Match match = FULL); // .f const_hdr_iterator beginh() const; // .f const_hdr_iterator endh() const; // .f const_reverse_hdr_iterator rbeginh() const; // .f const_reverse_hdr_iterator rendh() const; // .f // available from vector: size_t size() const; // .f std::string const &operator[](size_t idx) const; // opindex.f const_iterator begin() const; // .f const_iterator end() const; // .f const_reverse_iterator rbegin() const; // .f const_reverse_iterator rend() const; // .f }; #include "begin.f" #include "beginh.f" #include "end.f" #include "endh.f" #include "opindex.f" #include "rbegin.f" #include "rbeginh.f" #include "rend.f" #include "rendh.f" #include "setheaderiterator.f" #include "size.f" #include "oparrow.f" #include "opdec.f" #include "opeq.f" #include "opinc.f" #include "opneq.f" #include "oppostinc.f" #include "opstar.f" } // FBB #endif bobcat-3.19.01/mailheaders/rend.f0000644000175000017500000000014412223050627015456 0ustar frankfrankinline MailHeaders::const_reverse_iterator MailHeaders::rend() const { return d_lines.rend(); } bobcat-3.19.01/mailheaders/mailheaders1.cc0000644000175000017500000000023012222576531017227 0ustar frankfrank#include "mailheaders.ih" MailHeaders::MailHeaders(istream &in, Mode mode) : d_in(in), d_match(FAIL) { if (mode == READ) read(); } bobcat-3.19.01/mailheaders/consthdriterator1.cc0000644000175000017500000000065312222576531020360 0ustar frankfrank#include "mailheaders.ih" MailHeaders::const_hdr_iterator::const_hdr_iterator ( MailHeaders const *mh, MailHeaders::const_iterator begin ) : d_mh(mh), d_key ( static_cast(mh->d_match) < static_cast(MailHeaders::caseInsensitive) ? d_mh->d_hdr : String::lc(d_mh->d_hdr) ), d_comparator(s_comparator[mh->d_match]), d_current(lookup(begin)) {} bobcat-3.19.01/mailheaders/fail.f0000644000175000017500000000036112223071765015450 0ustar frankfrankinline bool MailHeaders::const_hdr_iterator::fail( string const &hdr, string const &key) { throw Exception(1) << "MailHeaders: setHeaderIterator() not called"; return false; // not reached } bobcat-3.19.01/mailheaders/initial.f0000644000175000017500000000027412223072031016154 0ustar frankfrankinline bool MailHeaders::const_hdr_iterator::initial( string const &hdr, string const &key) { return hdr.substr(0, hdr.find(':')).find(key) == 0; } bobcat-3.19.01/mailheaders/consthdropdec.cc0000644000175000017500000000035112224261645017532 0ustar frankfrank//#include "mailheaders.ih" // //MailHeaders::const_hdr_iterator //MailHeaders::const_hdr_iterator::operator--(int) //{ // const_hdr_iterator ret(d_mh, d_current); // d_current = lookdown(d_current); // // return ret; //} bobcat-3.19.01/mailheaders/mailheaders2.cc0000644000175000017500000000027112222576531017235 0ustar frankfrank#include "mailheaders.ih" MailHeaders::MailHeaders(MailHeaders &&tmp) : d_lines( move(tmp.d_lines) ), d_in(tmp.d_in), d_hdr( move(tmp.d_hdr) ), d_match(tmp.d_match) {} bobcat-3.19.01/mailheaders/full.f0000644000175000017500000000026112223072117015466 0ustar frankfrankinline bool MailHeaders::const_hdr_iterator::full( string const &hdr, string const &key) { return hdr.substr(0, hdr.find(':')) == key; } bobcat-3.19.01/mailheaders/partial.f0000644000175000017500000000030712223072067016165 0ustar frankfrankinline bool MailHeaders::const_hdr_iterator::partial( string const &hdr, string const &key) { return hdr.substr(0, hdr.find(':')).find(key) != string::npos; } bobcat-3.19.01/mailheaders/opstar.f0000644000175000017500000000015012223052051016024 0ustar frankfrankinline std::string const &MailHeaders::const_hdr_iterator::operator*() const { return *d_current; } bobcat-3.19.01/mailheaders/begin.f0000644000175000017500000000013612223050574015614 0ustar frankfrankinline MailHeaders::const_iterator MailHeaders::begin() const { return d_lines.begin(); } bobcat-3.19.01/mailheaders/driver/0000755000175000017500000000000012222576531015661 5ustar frankfrankbobcat-3.19.01/mailheaders/driver/build0000755000175000017500000003553512222576531016721 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/driver // script generated by the C++ icmake script version 2.13 /* Configurable defines for the build script: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (default: defined). COMPILER: The compiler to use. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM #define COMPILER "g++" #define COPT "-Wall" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current; // contains name of current dir. int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", interactive, "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD CLASSES = "parser scanner "; if (exists("parser")) // subdir parser exists parser(); if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { printf("\n"); exec(COMPILER, "-o", exe, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef GRAMBUILD "-lfl", #endif #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); #ifdef GRAMBUILD libs += " -lfl"; #endif cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "driver.cc", // program source "driver", // static program library "driver" // binary program ); #else cpp_make ( "", "driver", // static- or so-library "" ); #endif } bobcat-3.19.01/mailheaders/driver/spam10000644000175000017500000000646612222576531016641 0ustar frankfrankFrom hsookh1004@hanmail.net Sat Mar 22 17:54:59 2003 Received: from oosix.icce.rug.nl (oosix.icce.rug.nl [129.125.14.80]) by suffix.rc.rug.nl (8.12.3/8.12.3/Debian-5) with ESMTP id h2MGsxcA015750 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=FAIL) for ; Sat, 22 Mar 2003 17:54:59 +0100 Received: from relay.surfnet.nl (relay.surfnet.nl [192.87.5.144]) by oosix.icce.rug.nl (8.12.3/8.12.3/Debian-5) with ESMTP id h2MGswZ5005649 for ; Sat, 22 Mar 2003 17:54:59 +0100 Received: from icce.rug.nl (unknown [211.110.47.214]) by relay.surfnet.nl (Postfix) with SMTP id 9A76F43DB for ; Sat, 22 Mar 2003 17:54:57 +0100 (MET) From: Á¤¹Î°æ Subject: ±×³É »èÁ¦ÇϽÃÁö ¸¶½Ã°í Çѹø º¸¼¼¿ä..Èñ¸ÁÀÌ º¸ÀÔ´Ï´Ù........................................(±¤,.°í) Content-Type: text/html;charset=ks_c_5601-1987 Message-Id: <20030322165457.9A76F43DB@relay.surfnet.nl> Date: Sat, 22 Mar 2003 17:54:57 +0100 (MET) To: undisclosed-recipients:; Content-Length: 2322 Lines: 34
À§ ¹è³Ê´Â ¹ß¼ÛÀÚ ¹× ¸ÞÀϳ»¿ë°ú ¹«°üÇÕ´Ï´Ù.

¾È³çÇϼ¼¿ä...
±ÝÀ¶¿¡ °üÇÑ ¸ðµç ºñ¹ÐÀ» °ø°³ÇÕ´Ï´Ù. ´õÀÌ»ó ´ëÃâ¾÷Àڵ鿡°Ô ÀÚ½ÅÀÇ
Á¤º¸¸¦ ÁÖÁö ¸¶½Ã°í ¼ö¼ö·á ¾øÀÌ º»ÀÎÀÌ Á÷Á¢ ´ëÃâ¹Þ°Ô ÇØµå¸³´Ï´Ù.
¿©±â ÇöÁ÷ 16ÀÎÀÇ ±ÝÀ¶Àü¹®°¡°¡ ¿©·¯ºÐÀÇ °í¹ÎÀ» Çѹø¿¡ ÇØ°áÇØ
µå¸®°Ú½À´Ï´Ù..
                  
Áö±Ý Ŭ¸¯ Çϼ¼¿ä.

¿¹) Çö´ëÄ«µå ¾ß°£Áõ¾× 500¸¸¿øÀÌ»ó (ÁÖ°£¾ÈµÊ)
¿¹) Çö´ëÄ«µå ÁÖ°£¿¡ 1,000¸¸¿ø Áõ¾×°¡´É (¾ß°£¾ÈµÊ)
¿¹) LGÄ«µå Áï½Ã¹ß±Þ°ú µ¿½Ã¿¡ ¹°°Ç±¸ÀÔ Çϴ¹ý
¿¹) ½Å¿ëºÒ·®ÀÚ ´ëÃâ 400¸¸¿ø °¡´É (2±ºµ¥)
¿¹) Â÷ ¼³Á¤¾øÀÌ ÇÒºÎÇϰí Ÿ°í ´Ù´Ï´Â ¹æ¹ý
¿¹) ¹«Á÷ÀÚ ´ëÃâ¹æ¹ý °ø°³ (1,000¸¸¿ø ÀÌ»ó °¡´É)
¿¹) Çϳª(±¸ ¼­¿ï)ÀºÇà ÀüÈ­·Î ÇÑÅëÈ­·Î 500¸¸¿ø ´ëÃâ
¿¹) ¾ÆÆÄÆ® »ç½Ã´Â ¿©¼ººÐÀº 100 ~ 500¸¸¿ø ´ëÃâ
¿¹) ½Å¿ëºÒ·®ÀÚ ´çÀÏ´ëÃâ ¹æ¹ý
¿¹) ¿Üȯ, ±¹¹ÎÄ«µå 1Â÷, 2Â÷ Áõ¾×¹æ¹ý

                   Áö±Ý Click Çϼ¼¿ä.

´ëÃâ¿¡ °üÇÑ ³ëÇÏ¿ì 50¿©°³¿Í Ä«µåÀÇ °üÇÑ ³ëÇÏ¿ì 50¿©°³¸¦
16ÀÎÀÇ ÇöÁ÷±ÝÀ¶ÀÎÀÌ ¸ðµÎ °ø°³ÇÕ´Ï´Ù..
À̰Ŵ٠¶ó´Â ź¼º°ú ÇÔ²² ¿©·¯ºÐÀÇ °í¹ÎÀº »ç¶óÁú°ÍÀÔ´Ï´Ù.
ÀÌÁ¨ ´õÀÌ»ó ¾÷Àڵ鿡°Ô ÀÚ½ÅÀÇ Á¤º¸¸¦ ÁÖÁö ¸¶½Ã°í °í¾×ÀÇ ¼ö¼ö·á¾øÀÌ
º»ÀÎÀÌ Á÷Á¢ ´ëÃâÀ» ¹ÞÀ¸¼¼¿ä...

                   WWW.WAMONEY.CO.KR

* »ó±âÀÇ ¸ÞÀÏÀº ±¤°í ¸ñÀûÀ¸·Î ¹ß¼ÛµÇ¾ú½À´Ï´Ù.
* ¿øÇÏÁö ¾ÊÀ¸½Ã´Â °æ¿ì¿¡´Â ¼ö½Å°ÅºÎ ÇϽñ⠹ٶø´Ï´Ù.   ²Ù¹÷!²Ù¹÷!

bobcat-3.19.01/mailheaders/driver/driver.h0000644000175000017500000000017012222576531017323 0ustar frankfrank#ifndef INCLUDED_DRIVER_H_ #define INCLUDED_DRIVER_H_ #include #include namespace FBB { } #endif bobcat-3.19.01/mailheaders/driver/spam20000644000175000017500000000431412222576531016630 0ustar frankfrankFrom zjevf@excite.com Sat Mar 22 21:33:08 2003 Received: from dep.rc.rug.nl (dep.rc.rug.nl [129.125.3.10]) by suffix.rc.rug.nl (8.12.3/8.12.3/Debian-5) with ESMTP id h2MKX8c9019670 for ; Sat, 22 Mar 2003 21:33:08 +0100 Received: from excite.com (238.Red-80-36-13.pooles.rima-tde.net [80.36.13.238]) by dep.rc.rug.nl (8.9.3/8.9.3) with SMTP id VAA08234 for ; Sat, 22 Mar 2003 21:32:49 +0100 (MET) From: zjevf@excite.com Message-ID: <000510c6ea03$cce35275$28363632@qfafjfk.obp> To: Subject: A n t i * A g i n g M_i_r_a_c_l_e W_o_r_k_e_r 4883bLIH1-029NQXx2510vRym-24 Date: Sun, 23 Mar 2003 03:16:39 -0800 MIME-Version: 1.0 Content-Type: text/html; charset="iso-8859-1" X-Priority: 3 X-Mailer: Microsoft Outlook Express 5.00.2615.200 Importance: Normal Content-Length: 1350 Lines: 27 Message

* Reduce the amount of sleep you need
* Cause wounds to heal faster
* Lose weight while your sleeping
* Become less winded when excersizing
* Put color back in grey hair
* Grow hair back where it had once fallen out
* Tighten skin
* Strengthen bones
* Body builders - use this to build your muscles quicker
.........The List truly goes on and on..........

As seen on NBC, CBS, CNN, and Oprah! The health discovery
that actually reverses aging symptoms without dieting or exercise!
This PROVEN FDA approved discovery has been reported on by the
New England Journal of Medicine - don't just take our word for it.

In fact we'd like you to receive a F.R.E.E thirty day supply; look and feel
younger, lose weight, reduce sleep, The list goes on, we
encourage you to at least take a look at the information as to
what else it can do.

CLICK HERE

If the above link doesn't work: CLICK HERE

4837qhzz8-768bqfj0549vZSa3-859Vvll2323eyOG2-477Yltl47 bobcat-3.19.01/mailheaders/driver/driver.ih0000644000175000017500000000014612222576531017477 0ustar frankfrank#include "driver.h" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/mailheaders/driver/mail.hein0000644000175000017500000001320212222576531017446 0ustar frankfrankFrom frank@suffix.rc.rug.nl Sun Mar 2 21:11:01 2003 Return-Path: Received: from suffix.rc.rug.nl (suffix.rc.rug.nl [129.125.3.162]) by knarfix.oostum.north (8.12.3/8.12.3/Debian -4) with ESMTP id h22KAvQp011565 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=FAIL) for ; Sun, 2 Mar 2003 21:10:59 +0100 Received: from suffix.rc.rug.nl (localhost [127.0.0.1]) by suffix.rc.rug.nl (8.12.3/8.12.3/Debian -4) with ESMTP id h22KAqCb003128 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=FAIL) for ; Sun, 2 Mar 2003 21:10:52 +0100 Received: (from frank@localhost) by suffix.rc.rug.nl (8.12.3/8.12.3/Debian -4) id h22KAqvc003127 for frank@dial30.service.rug.nl; Sun, 2 Mar 2003 21:10:52 +0100 Resent-Message-Id: <200303022010.h22KAqvc003127@suffix.rc.rug.nl> Received: from dep.rc.rug.nl (dep.rc.rug.nl [129.125.3.10]) by suffix.rc.rug.nl (8.12.3/8.12.3/Debian -4) with ESMTP id h1EJJ9Sj011249 for ; Fri, 14 Feb 2003 20:19:09 +0100 Received: from mano.soest.hawaii.edu (mano.soest.hawaii.edu [128.171.151.45]) by dep.rc.rug.nl (8.9.3/8.9.3) with ESMTP id UAA18183 for ; Fri, 14 Feb 2003 20:18:43 +0100 (MET) Received: from equator.soest.hawaii.edu (IDENT:root@equator [128.171.151.54]) by mano.soest.hawaii.edu (8.12.1/8.12.1) with ESMTP id h1EJJ1Jv003882 for ; Fri, 14 Feb 2003 09:19:02 -1000 (HST) Received: (from hein@localhost) by equator.soest.hawaii.edu (8.11.6/8.11.6) id h1EJJ0R01740 for f.b.brokken@rc.rug.nl; Fri, 14 Feb 2003 09:19:00 -1000 Date: Fri, 14 Feb 2003 09:19:00 -1000 From: Hein Zelle To: "Frank B. Brokken" Subject: Re: iterators + annotations Message-ID: <20030214191900.GA1667@equator.soest.hawaii.edu> References: <20030207185644.GA1714@equator.soest.hawaii.edu> <20030213131606.GA7329@rc.rug.nl> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20030213131606.GA7329@rc.rug.nl> Resent-From: frank@rc.rug.nl Resent-Date: Sun, 2 Mar 2003 21:10:52 +0100 Resent-To: frank@dial30.service.rug.nl Status: RO Content-Length: 3503 Lines: 79 Hoi Frank, > moet-ie ook worden geinitialiseerd. Maar de volgende truuk leert je dat een > iterator normaliter op 0 is geinitialiseerd: > > int main(int argc, char *argv[]) > { > vector::iterator vi; > > cout << &*vi << endl; > } Ah, dat dacht ik al maar ik wist het niet zeker. Ik heb dit misschien nodig, tenzij ik jouw truuk van een lege static member vector gebruik. Probleem is namelijk dat de class met de iterator niet weet naar welke vector hij wijst, en dus ook niet kan vergelijken met vector.end(). (Of dat wenselijk is is vraag 2, maar goed) Ik denk dat de static member oplossing het mooist is. > end() kan volgens mij prima, want end() wijst dan toch al voorbij het laatste > element. begin() is dan direct al end(): de volgende code levert `gelijk' Dat is goed om te weten. Misschien is dat iets om expliciet in de annotations te vermelden: het werd mij niet helemaal duidelijk welke members van een lege vector je nou wel en niet mag aanroepen. > Wb een eerdere mail, over Java: ik ben niet zo blij met Java. Er zitten een > paar onlogische constructies in ... [knip knip] Bedankt voor je uitleg, dat was ook mijn eerste indruk. Bevestigt mijn idee dat ik het niet hoef te leren totdat ik echt behoefte krijg aan web-applicaties of iets dergelijks. (Alhoewel de basis niet zo moeilijk lijkt, gaat er waarschijnlijk een hoop tijd zitten in het leren van die 2000 classes ...) > De basis gedachte is: er gebeuren dingen die ik niet beheers, en > waar ik mogelijk niet om heb gevraagd. Daar heb ik een grote hekel > aan in programmeertalen. Idem. Dat vind ik een goed argument om het niet te gebruiken, mits je een alternatief hebt natuurlijk. Helemaal nu ik de STL van C++ begin te kennen en begrijpen, zie ik het nut van java niet zo in (voor mij). De STL vult het voornaamste gat in wat er nog was: een standaard oplossing voor de dingen die je anders bij ieder project weer opnieuw maakt. Met name vector en list vind ik een fantastische uitvinding. (en de algoritmes als sort()) > Verder heb ik wel eens gekeken naar 't verschil tussen een complex C++ > programma en hetzelfde Java programma: Java runt 10 x zo traag en gebruikt 10 > x zoveel geheugen. Ik kan aardig omgaan met Java, en leer KI-studenten hier > programmeren mbv Java, maar ik ben er bepaald niet juichend enthousiast > over. C/C++ vind ik nog steeds in hoge mate te prefereren boven Java. Over runtime performance van java: daar zijn ze bij sun nu blijkbaar ook achter gekomen. Als je tijd hebt vind je het volgende artikel misschien wel interessant: een intern memo van SUN over de redenen waarom java niet breed geaccepteerd wordt. (niet van de origine site, dit is een mirror, originele adres ben ik kwijt) http://www.misura.org/temp/JavaInternalMemo.html > Sorry voor de late reactie(s), maar soms heb ik 't hier even een beetje > druk. Wellicht heb je (nog) iets aan mijn verlate reacties. Ben je mal, natuurlijk snap ik dat je het druk hebt. Mijn mail over java was bepaald niet dringend, en het helpt zeker om er van jou wat over te horen, omdat jij er daadwerkelijk mee gewerkt hebt. Bedankt en groeten (uit een druilerig Hawaii) Hein >-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-< Unix is user friendly. It's just very particular about who it's friends are. Hein Zelle hein@icce.rug.nl http://www.icce.rug.nl/~hein >-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-< bobcat-3.19.01/mailheaders/driver/mail0000644000175000017500000001345012222576531016531 0ustar frankfrankFrom m.pattiapon@rc.rug.nl Mon Jul 15 13:56:57 2002 Received: from oosix.icce.rug.nl (oosix.icce.rug.nl [129.125.14.80]) by suffix.icce.rug.nl (8.12.3/8.12.3/Debian -4) with ESMTP id g6FButlO018423 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=FAIL) for ; Mon, 15 Jul 2002 13:56:57 +0200 Received: from rug.nl (imap.rc.rug.nl [129.125.50.21]) by oosix.icce.rug.nl (8.12.3/8.12.3/Debian -4) with ESMTP id g6FBut14018196 for ; Mon, 15 Jul 2002 13:56:55 +0200 Received: from by rug.nl (CommuniGate Pro RULES 3.5.9) with RULES id 175635; Mon, 15 Jul 2002 13:56:56 +0200 X-Autogenerated: Mirror X-Mirrored-by: (F.B.Brokken) Received: from dep.rc.rug.nl ([129.125.3.10] verified) by rug.nl (CommuniGate Pro SMTP 3.5.9) with ESMTP id 175634 for brokken@imap.rc.rug.nl; Mon, 15 Jul 2002 13:56:55 +0200 Received: from rc-285 (rc-285.rc.rug.nl [129.125.3.72]) by dep.rc.rug.nl (8.9.3/8.9.3) with ESMTP id NAA21616 for ; Mon, 15 Jul 2002 13:56:55 +0200 From: "Magda Pattiapon" Organization: Rekencentrum RUG To: F.B.Brokken@rc.rug.nl Date: Mon, 15 Jul 2002 13:56:54 +0200 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: fakemails chello Reply-to: m.pattiapon@rc.rug.nl Message-ID: <3D32D4A5.1582.5D218B74@localhost> Priority: normal Status: RO Content-Length: 4411 Lines: 70 Jul 12 18:04:51 dep sendmail[16508]: SAA16508: from=, size=41126, class=0, pri=71126, nrcpts=1, msgid=<200207121604.SAA16508@dep.rc.rug.nl>, proto=SMTP, relay=a106005.upc-a.chello.nl [62.163.106.5] Jul 12 18:04:51 dep sendmail[16510]: SAA16508: to=brokken@imap.rc.rug.nl, delay=00:00:03, xdelay=00:00:00, mailer=esmtp, relay=imap.rc.rug.nl. [129.125.50.21], stat=Sent (173817 message accepted for delivery) Jul 12 18:04:51 dep sendmail[16510]: SAA16508: to=brokken@rc2000.rc.rug.nl, delay=00:00:03, xdelay=00:00:00, mailer=esmtp, relay=rc2000.rc.rug.nl. [129.125.3.3], stat=Sent (Data received OK.) Jul 12 18:12:42 dep sendmail[16585]: SAA16585: from=, size=41147, class=0, pri=71147, nrcpts=1, msgid=<200207121612.SAA16585@dep.rc.rug.nl>, proto=SMTP, relay=a106005.upc-a.chello.nl [62.163.106.5] Jul 12 18:12:42 dep sendmail[16588]: SAA16585: to=brokken@imap.rc.rug.nl, delay=00:00:03, xdelay=00:00:00, mailer=esmtp, relay=imap.rc.rug.nl. [129.125.50.21], stat=Sent (173824 message accepted for delivery) Jul 12 18:12:42 dep sendmail[16588]: SAA16585: to=brokken@rc2000.rc.rug.nl, delay=00:00:03, xdelay=00:00:00, mailer=esmtp, relay=rc2000.rc.rug.nl. [129.125.3.3], stat=Sent (Data received OK.) Jul 12 18:19:25 dep sendmail[16650]: SAA16650: from=, size=41127, class=0, pri=71127, nrcpts=1, msgid=<200207121619.SAA16650@dep.rc.rug.nl>, proto=SMTP, relay=a106005.upc-a.chello.nl [62.163.106.5] Jul 12 18:19:25 dep sendmail[16651]: SAA16650: to=brokken@imap.rc.rug.nl, delay=00:00:04, xdelay=00:00:00, mailer=esmtp, relay=imap.rc.rug.nl. [129.125.50.21], stat=Sent (173833 message accepted for delivery) Jul 12 18:19:25 dep sendmail[16651]: SAA16650: to=brokken@rc2000.rc.rug.nl, delay=00:00:04, xdelay=00:00:00, mailer=esmtp, relay=rc2000.rc.rug.nl. [129.125.3.3], stat=Sent (Data received OK.) Jul 12 18:25:14 dep sendmail[16691]: SAA16691: from=, size=42320, class=0, pri=72320, nrcpts=1, msgid=<200207121625.SAA16691@dep.rc.rug.nl>, proto=SMTP, relay=a106005.upc-a.chello.nl [62.163.106.5] Jul 12 18:25:14 dep sendmail[16693]: SAA16691: to=brokken@imap.rc.rug.nl, delay=00:00:04, xdelay=00:00:00, mailer=esmtp, relay=imap.rc.rug.nl. [129.125.50.21], stat=Sent (173839 message accepted for delivery) Jul 12 18:25:14 dep sendmail[16693]: SAA16691: to=brokken@rc2000.rc.rug.nl, delay=00:00:04, xdelay=00:00:00, mailer=esmtp, relay=rc2000.rc.rug.nl. [129.125.3.3], stat=Sent (Data received OK.) Jul 12 18:29:24 dep sendmail[16738]: SAA16738: from=, size=41140, class=0, pri=71140, nrcpts=1, msgid=<200207121629.SAA16738@dep.rc.rug.nl>, proto=SMTP, relay=a106005.upc-a.chello.nl [62.163.106.5] Jul 12 18:29:24 dep sendmail[16739]: SAA16738: to=brokken@imap.rc.rug.nl, delay=00:00:03, xdelay=00:00:00, mailer=esmtp, relay=imap.rc.rug.nl. [129.125.50.21], stat=Sent (173845 message accepted for delivery) Jul 12 18:29:24 dep sendmail[16739]: SAA16738: to=brokken@rc2000.rc.rug.nl, delay=00:00:03, xdelay=00:00:00, mailer=esmtp, relay=rc2000.rc.rug.nl. [129.125.3.3], stat=Sent (Data received OK.) Jul 12 18:35:52 dep sendmail[16800]: SAA16800: from=, size=42316, class=0, pri=72316, nrcpts=1, msgid=<200207121635.SAA16800@dep.rc.rug.nl>, proto=SMTP, relay=a106005.upc-a.chello.nl [62.163.106.5] Jul 12 18:35:52 dep sendmail[16801]: SAA16800: to=brokken@imap.rc.rug.nl, delay=00:00:03, xdelay=00:00:00, mailer=esmtp, relay=imap.rc.rug.nl. [129.125.50.21], stat=Sent (173851 message accepted for delivery) Jul 12 18:35:53 dep sendmail[16801]: SAA16800: to=brokken@rc2000.rc.rug.nl, delay=00:00:04, xdelay=00:00:01, mailer=esmtp, relay=rc2000.rc.rug.nl. [129.125.3.3], stat=Sent (Data received OK.) Jul 12 18:42:52 dep sendmail[16864]: SAA16864: from=, size=42312, class=0, pri=72312, nrcpts=1, msgid=<200207121642.SAA16864@dep.rc.rug.nl>, proto=SMTP, relay=a106005.upc-a.chello.nl [62.163.106.5] Jul 12 18:42:52 dep sendmail[16865]: SAA16864: to=brokken@imap.rc.rug.nl, delay=00:00:04, xdelay=00:00:00, mailer=esmtp, relay=imap.rc.rug.nl. [129.125.50.21], stat=Sent (173858 message accepted for delivery) Jul 12 18:42:53 dep sendmail[16865]: SAA16864: to=brokken@rc2000.rc.rug.nl, delay=00:00:05, xdelay=00:00:01, mailer=esmtp, relay=rc2000.rc.rug.nl. [129.125.3.3], stat=Sent (Data received OK.) bobcat-3.19.01/mailheaders/driver/driver.cc0000644000175000017500000000233012222576531017461 0ustar frankfrank/* driver.cc */ #include "driver.h" #include "../mailheaders" #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { MailHeaders mh(cin, MailHeaders::DONT_READ); try { mh.read(); } catch (Errno &err) { cout << err.why() << endl; } mh.setHeaderIterator("Received"); cout << "=================================== All mail headers:\n"; copy(mh.begin(), mh.end(), ostream_iterator(cout, "\n")); cout << "=============================== First and last but 1 hdr:\n"; cout << mh[0] << endl << mh[mh.size() - 2] << endl; cout << "====================== Received: headers:\n"; copy(mh.beginh(), mh.endh(), ostream_iterator(cout, "\n")); cout << "====================== Received: headers, reversed order:\n"; copy(mh.rbeginh(), mh.rendh(), ostream_iterator(cout, "\n")); cout << "====================== all From headers:\n"; mh.setHeaderIterator("From", MailHeaders::PARTIAL); copy(mh.beginh(), mh.endh(), ostream_iterator(cout, "\n")); return 0; } bobcat-3.19.01/mailheaders/caseinitial.f0000644000175000017500000000031412223072157017014 0ustar frankfrankinline bool MailHeaders::const_hdr_iterator::caseInitial( string const &hdr, string const &key) { return String::lc(hdr.substr(0, hdr.find(':'))).find(key) == 0; } bobcat-3.19.01/mailheaders/mailheaders.ih0000644000175000017500000000044412223072300017152 0ustar frankfrank#include "mailheaders" #include #include #include using namespace std; using namespace FBB; #include "casefull.f" #include "caseinitial.f" #include "casepartial.f" #include "fail.f" #include "full.f" #include "initial.f" #include "partial.f" bobcat-3.19.01/mailheaders/data.cc0000644000175000017500000000034212222576531015605 0ustar frankfrank#include "mailheaders.ih" MailHeaders::const_hdr_iterator::Comparator MailHeaders::const_hdr_iterator::s_comparator[] = { fail, initial, partial, full, caseInitial, casePartial, caseFull }; bobcat-3.19.01/mailheaders/rendh.f0000644000175000017500000000017712223051212015623 0ustar frankfrankinline MailHeaders::const_reverse_hdr_iterator MailHeaders::rendh() const { return const_reverse_hdr_iterator(beginh()); } bobcat-3.19.01/mailheaders/rbeginh.f0000644000175000017500000000017712223051230016141 0ustar frankfrankinline MailHeaders::const_reverse_hdr_iterator MailHeaders::rbeginh() const { return const_reverse_hdr_iterator(endh()); } bobcat-3.19.01/mailheaders/opeq.f0000644000175000017500000000026112223051772015474 0ustar frankfrankinline bool MailHeaders::const_hdr_iterator::operator==( const_hdr_iterator const &other) const { return d_current == other.d_current; } bobcat-3.19.01/mailheaders/iteratorclass.demo0000644000175000017500000000266012222576531020117 0ustar frankfrank/* class const_iterator: public std::iterator { friend class MailHeaders; MailHeaders const &d_mh; Hdr::const_iterator d_begin; Hdr::const_iterator d_end; public: const_iterator(MailHeaders const &mh, char const *hdr, Match match, Where where); const_iterator &operator++(); const_iterator const operator++(int); const *operator->() { return ; } const &operator*() { return *operator->(); } bool operator==(const_iterator const &rvalue) const { return &d_mh == &rvalue.d_mh && d_begin == rvalue.d_begin; } bool operator!=(const_iterator const &rvalue) const { return !operator==(rvalue); } private: const_iterator &operator--(); const_iterator const operator--(int); }; friend class MailHeaders::const_iterator; */ bobcat-3.19.01/mailheaders/opneq.f0000644000175000017500000000026112223052015015641 0ustar frankfrankinline bool MailHeaders::const_hdr_iterator::operator!=( const_hdr_iterator const &other) const { return d_current != other.d_current; } bobcat-3.19.01/mailheaders/end.f0000644000175000017500000000013212223050644015270 0ustar frankfrankinline MailHeaders::const_iterator MailHeaders::end() const { return d_lines.end(); } bobcat-3.19.01/mailheaders/opdec.f0000644000175000017500000000022212223051443015612 0ustar frankfrankinline MailHeaders::const_hdr_iterator &MailHeaders::const_hdr_iterator::operator--() { d_current = lookdown(d_current); return *this; } bobcat-3.19.01/mailheaders/read.cc0000644000175000017500000000210712222576531015610 0ustar frankfrank#include "mailheaders.ih" void MailHeaders::read() { static char funName[] = "MailHeaders::read()"; if (size()) throw Exception() << funName << "Mail headers already read"; while (true) { string line; if (!getline(d_in, line)) // no more header lines throw Exception() << funName << // is an error condition "Headers incomplete after line " << d_lines.size(); if (line.find_first_not_of(" \t") == string::npos) // blank line { d_lines.resize(size() + 1); // last line will be used as // the search sentinel return; } if (line[0] != ' ' && line[0] != '\t') // add the new header line d_lines.push_back(line); else { if (not d_lines.size()) // no header yet: error throw Exception() << funName << "Invalid begin of headers"; (d_lines.back() += "\n") += line; // add line continuation } } } bobcat-3.19.01/mailheaders/endh.f0000644000175000017500000000027512223051154015445 0ustar frankfrankinline MailHeaders::const_hdr_iterator MailHeaders::endh() const { // returns address of the sentinel return const_hdr_iterator(this, end()); } bobcat-3.19.01/mailheaders/lookup.cc0000644000175000017500000000066112222576531016211 0ustar frankfrank#include "mailheaders.ih" MailHeaders::const_iterator MailHeaders::const_hdr_iterator::lookup (const_iterator const &begin) const { const_iterator next = find_if(begin, d_mh->end(), [&](std::string const &header) { return (*d_comparator)(header, d_key); } ); return next; } bobcat-3.19.01/mailheaders/casepartial.f0000644000175000017500000000032712223072236017021 0ustar frankfrankinline bool MailHeaders::const_hdr_iterator::casePartial( string const &hdr, string const &key) { return String::lc(hdr.substr(0, hdr.find(':'))).find(key) != string::npos; } bobcat-3.19.01/mailheaders/operatorassign.cc0000644000175000017500000000020012222576531017725 0ustar frankfrank#include "mailheaders.ih" MailHeaders &MailHeaders::operator=(MailHeaders &&tmp) { fswap(*this, tmp); return *this; } bobcat-3.19.01/mailheaders/opinc.f0000644000175000017500000000022212223051315015626 0ustar frankfrankinline MailHeaders::const_hdr_iterator &MailHeaders::const_hdr_iterator::operator++() { d_current = lookup(++d_current); return *this; } bobcat-3.19.01/mailheaders/opindex.f0000644000175000017500000000014112223050752016170 0ustar frankfrankinline std::string const &MailHeaders::operator[](size_t idx) const { return d_lines[idx]; } bobcat-3.19.01/mailheaders/lookdown.cc0000644000175000017500000000103312222576531016526 0ustar frankfrank#include "mailheaders.ih" MailHeaders::const_iterator MailHeaders::const_hdr_iterator::lookdown (const_iterator const &begin) const { return d_mh->begin() + ( &*find_if( const_reverse_iterator(begin), d_mh->rend(), [&](std::string const &header) { return (*d_comparator)(header, d_key); } ) - &*d_mh->begin() ); } bobcat-3.19.01/mailheaders/casefull.f0000644000175000017500000000030112223072266016322 0ustar frankfrankinline bool MailHeaders::const_hdr_iterator::caseFull( string const &hdr, string const &key) { return String::lc(hdr.substr(0, hdr.find(':'))) == key; } bobcat-3.19.01/mbuf/0000755000175000017500000000000012242431634013035 5ustar frankfrankbobcat-3.19.01/mbuf/nolinenr.f0000644000175000017500000000007312223072776015037 0ustar frankfrankinline void Mbuf::noLineNr() { d_showLineNr = false; } bobcat-3.19.01/mbuf/mbuf0000644000175000017500000000617612223073300013712 0ustar frankfrank#ifndef INCLUDED_BOBCAT_MBUF_ #define INCLUDED_BOBCAT_MBUF_ #include #include #include #include #include #include namespace FBB { class Mbuf: public std::streambuf { std::shared_ptr d_ofstr; std::ostream d_ostr; // this is the receiving ostream bool d_firstChar; bool d_throw; std::string d_tag; size_t d_count; // counts # messages size_t d_maxCount; bool d_lineExcess; bool d_showLineNr; size_t d_lineNr; std::string d_lineTag; public: Mbuf(); // 1 explicit Mbuf(std::streambuf *strbuf, // 2 size_t maxCount = std::numeric_limits::max(), std::string const &tag = "", bool throwing = false); // 3 explicit Mbuf(std::string const &name, size_t maxCount = std::numeric_limits::max(), std::string const &tag = "", bool throwing = false); void reset(Mbuf const &mbuf); // 1: initialize from // mbuf. Shares // d_ofstr and uses // d_ostr's rdbuf void reset(std::streambuf *strbuf, size_t maxCount, // 2 std::string const &tag, bool throwing); void reset(std::string const &name, size_t maxCount, // 3 std::string const &tag, bool throwing); bool throws() const; // .f void throwing(bool ifTrue); // .f size_t count() const; // .f size_t maxCount() const; // .f std::string const &tag() const; // .f std::string const &lineTag() const; // .f void noLineNr(); // .f void setLineNr(size_t lineNr); void setCount(size_t count); // .f void setMaxCount(size_t maxCount); // .f void setTag(std::string const &tag); void setLineTag(std::string const &lineTag); // .f bool lineExcess() const; // .f private: void atFirstChar(); bool firstChar() const; void showTag(); void inspectOfstr(std::string const &name) const; virtual int overflow(int c); virtual std::streamsize xsputn(char const *buf, std::streamsize n); virtual int sync(); }; #include "count.f" #include "lineexcess.f" #include "linetag.f" #include "maxcount.f" #include "nolinenr.f" #include "setcount.f" #include "setlinetag.f" #include "setmaxcount.f" #include "tag.f" #include "throwing.f" #include "throws.f" } // FBB #endif bobcat-3.19.01/mbuf/reset3.cc0000644000175000017500000000072212222576523014557 0ustar frankfrank#include "mbuf.ih" void Mbuf::reset(string const &name, size_t maxCount, string const &tag, bool throwing) { sync(); if (d_ofstr->rdbuf() == d_ostr.rdbuf()) d_ofstr.reset(); d_ofstr = shared_ptr(new ofstream(name)); d_ostr.rdbuf(d_ofstr->rdbuf()), d_firstChar = true; d_throw = throwing; setTag(tag); d_maxCount = maxCount; d_lineExcess = d_count >= maxCount; inspectOfstr(name); } bobcat-3.19.01/mbuf/mbuf3.cc0000644000175000017500000000127512222576523014372 0ustar frankfrank#include "mbuf.ih" Mbuf::Mbuf(string const &name, size_t maxCount, string const &tag, bool throwing) : d_ofstr(new ofstream(name)), d_ostr(d_ofstr->rdbuf()), d_firstChar(true), d_throw(throwing), d_count(0), d_maxCount(maxCount), d_lineExcess(maxCount == 0), d_showLineNr(false), d_lineNr(0), d_lineTag("Line") { setTag(tag); inspectOfstr(name); } // If a MsgStream is created by name and a second MsgStream is intialized // using the initial stream's MsgBuf then the initial MsgStream should outlive // the second MsgStream. If not then the 2nd MsgStream's MsgBuf::d_ostr will // no longer refer to a valid streambuf. bobcat-3.19.01/mbuf/throwing.f0000644000175000017500000000010212223073022015026 0ustar frankfrankinline void Mbuf::throwing(bool ifTrue) { d_throw = ifTrue; } bobcat-3.19.01/mbuf/showtag.cc0000644000175000017500000000037312222576523015030 0ustar frankfrank#include "mbuf.ih" void Mbuf::showTag() { if (d_tag.empty()) return; d_ostr << d_tag; // starts with [ if (d_maxCount != numeric_limits::max()) d_ostr << ' ' << d_count; d_ostr << "] "; } bobcat-3.19.01/mbuf/xsputn.cc0000644000175000017500000000030112222576523014704 0ustar frankfrank#include "mbuf.ih" std::streamsize Mbuf::xsputn(char const *buf, std::streamsize n) { atFirstChar(); d_ostr.write(buf, n); return n; // only if the write succeeded } bobcat-3.19.01/mbuf/throws.f0000644000175000017500000000007112223073065014527 0ustar frankfrankinline bool Mbuf::throws() const { return d_throw; } bobcat-3.19.01/mbuf/linetag.f0000644000175000017500000000011212223072732014620 0ustar frankfrankinline std::string const &Mbuf::lineTag() const { return d_lineTag; } bobcat-3.19.01/mbuf/reset2.cc0000644000175000017500000000056012222576523014556 0ustar frankfrank#include "mbuf.ih" void Mbuf::reset(streambuf *buf, size_t maxCount, string const &tag, bool throwing) { sync(); if (d_ofstr->rdbuf() == d_ostr.rdbuf()) d_ofstr.reset(); d_ostr.rdbuf(buf); d_firstChar = true; d_throw = throwing; setTag(tag); d_maxCount = maxCount; d_lineExcess = d_count >= maxCount; } bobcat-3.19.01/mbuf/mbuf.ih0000644000175000017500000000022212222576523014311 0ustar frankfrank#include "mbuf" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/mbuf/mbuf.cc0000644000175000017500000000002512222576523014277 0ustar frankfrank#include "mbuf.ih" bobcat-3.19.01/mbuf/setmaxcount.f0000644000175000017500000000011612223073117015551 0ustar frankfrankinline void Mbuf::setMaxCount(size_t maxCount) { d_maxCount = maxCount; } bobcat-3.19.01/mbuf/inspectofstr.cc0000644000175000017500000000024712222576523016077 0ustar frankfrank#include "mbuf.ih" void Mbuf::inspectOfstr(string const &name) const { if (not d_ofstr->good()) throw Exception(1) << "Can't write `" << name << '\''; } bobcat-3.19.01/mbuf/reset1.cc0000644000175000017500000000070512222576523014556 0ustar frankfrank#include "mbuf.ih" void Mbuf::reset(Mbuf const &other) { sync(); d_ofstr = other.d_ofstr; d_ostr.rdbuf(other.d_ostr.rdbuf()); d_firstChar = true; d_throw = other.d_throw; d_tag = other.d_tag; d_count = other.d_count; d_maxCount = other.d_maxCount; d_lineExcess = other.d_lineExcess; d_showLineNr = other.d_showLineNr; d_lineNr = other.d_lineNr; d_lineTag = other.d_lineTag; } bobcat-3.19.01/mbuf/setlinetag.f0000644000175000017500000000012612223073167015344 0ustar frankfrankinline void Mbuf::setLineTag(std::string const &lineTag) { d_lineTag = lineTag; } bobcat-3.19.01/mbuf/driver/0000755000175000017500000000000012222576523014335 5ustar frankfrankbobcat-3.19.01/mbuf/driver/build0000755000175000017500000000036312222576523015364 0ustar frankfrank#!/bin/bash #CMD="g++ --std=c++0x -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib \ # -lbobcat -s" CMD="g++ --std=c++0x -o driver -Wall driver.cc ../*.o -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/mbuf/driver/driver.cc0000644000175000017500000000127612222576523016145 0ustar frankfrank#include "../msgbuf" #include #include using namespace std; using namespace FBB; using namespace FBB::BOBCAT; int main() { ostream os(cout.rdbuf()); Msgbuf msb(&os); Msg ms(msb); string s; ms << "hello world" << s << 12 << endl; // explicit flush os.setstate(ios::badbit); ms << "this should fail" << endl; // explicit flush os.clear(); ms << "this should be shown" << endl; // explicit flush msb.reset(&cout, true); // throwing buffer try { ms << "Following this, we throw" << endl; } catch(Errno const &err) { cout << "Caught Errno exception" << endl; } } bobcat-3.19.01/mbuf/tag.f0000644000175000017500000000010212223072672013752 0ustar frankfrankinline std::string const &Mbuf::tag() const { return d_tag; } bobcat-3.19.01/mbuf/count.f0000644000175000017500000000007212223073264014333 0ustar frankfrankinline size_t Mbuf::count() const { return d_count; } bobcat-3.19.01/mbuf/atfirstchar.cc0000644000175000017500000000103212222576523015657 0ustar frankfrank#include "mbuf.ih" void Mbuf::atFirstChar() { if (not d_firstChar) return; d_firstChar = false; ++d_count; d_lineExcess = d_count + 1 > d_maxCount; // if d_maxCount == UINT_MAX // then this is never true if (d_lineExcess) { d_ostr.setstate(ios::badbit); return; } if (d_tag.length()) showTag(); if (d_showLineNr) { d_showLineNr = false; d_ostr << d_lineTag << ' ' << d_lineNr << ": "; } } bobcat-3.19.01/mbuf/overflow.cc0000644000175000017500000000014712222576523015216 0ustar frankfrank#include "mbuf.ih" int Mbuf::overflow(int c) { atFirstChar(); d_ostr.put(c); return c; } bobcat-3.19.01/mbuf/mbuf2.cc0000644000175000017500000000054312222576523014366 0ustar frankfrank#include "mbuf.ih" Mbuf::Mbuf(streambuf *buf, size_t maxCount, string const &tag, bool throwing) : d_ostr(buf), d_firstChar(true), d_throw(throwing), d_count(0), d_maxCount(maxCount), d_lineExcess(maxCount == 0), d_showLineNr(false), d_lineNr(0), d_lineTag("Line") { setTag(tag); } bobcat-3.19.01/mbuf/setlinenr.cc0000644000175000017500000000015512222576523015355 0ustar frankfrank#include "mbuf.ih" void Mbuf::setLineNr(size_t lineNr) { d_lineNr = lineNr; d_showLineNr = true; } bobcat-3.19.01/mbuf/mbuf1.cc0000644000175000017500000000040612222576523014363 0ustar frankfrank#include "mbuf.ih" Mbuf::Mbuf() : d_ostr(cout.rdbuf()), d_firstChar(true), d_throw(false), d_count(0), d_maxCount(numeric_limits::max()), d_lineExcess(false), d_showLineNr(false), d_lineNr(0), d_lineTag("Line") {} bobcat-3.19.01/mbuf/lineexcess.f0000644000175000017500000000010212223072652015337 0ustar frankfrankinline bool Mbuf::lineExcess() const { return d_lineExcess; } bobcat-3.19.01/mbuf/setcount.f0000644000175000017500000000010212223073212015032 0ustar frankfrankinline void Mbuf::setCount(size_t count) { d_count = count; } bobcat-3.19.01/mbuf/showlinenr.cc0000644000175000017500000000016412222576523015542 0ustar frankfrank#include "mbuf.ih" inline void Mbuf::setLineNr(size_t lineNr) { d_showLineNr = true; d_lineNr = lineNr; } bobcat-3.19.01/mbuf/settag.cc0000644000175000017500000000015112222576523014635 0ustar frankfrank#include "mbuf.ih" void Mbuf::setTag(string const &tag) { d_tag = tag.length() ? '[' + tag : tag; } bobcat-3.19.01/mbuf/sync.cc0000644000175000017500000000014412222576523014324 0ustar frankfrank#include "mbuf.ih" int Mbuf::sync() { d_ostr.flush(); d_firstChar = true; return 0; } bobcat-3.19.01/mbuf/maxcount.f0000644000175000017500000000010012223072605015027 0ustar frankfrankinline size_t Mbuf::maxCount() const { return d_maxCount; } bobcat-3.19.01/milter/0000755000175000017500000000000012257325714013407 5ustar frankfrankbobcat-3.19.01/milter/mclose.cc0000644000175000017500000000062612222611511015165 0ustar frankfrank#include "milter.ih" sfsistat Milter::mClose(SMFICTX *ctx) { iterator it = s_map.find(ctx); sfsistat ret = SMFIS_CONTINUE; if (it != s_map.end()) // installed. { if (s_callClose) ret = it->second->close(); delete it->second; // delete this Milter s_map.erase(it); // and erase from the map } return ret; } bobcat-3.19.01/milter/destructor.cc0000644000175000017500000000005312222611511016073 0ustar frankfrank#include "milter.ih" Milter::~Milter() {} bobcat-3.19.01/milter/eoh.cc0000644000175000017500000000010612222611511014447 0ustar frankfrank#include "milter.ih" sfsistat Milter::eoh() { return CONTINUE; } bobcat-3.19.01/milter/milter0000644000175000017500000002443112222576524014631 0ustar frankfrank#ifndef INCLUDED_BOBCAT_MILTER_ #define INCLUDED_BOBCAT_MILTER_ #include #include #include #include #include namespace FBB { class Milter { static std::string s_name; static Milter *s_mp; static bool s_callClose; typedef std::unordered_map::iterator iterator; static std::unordered_map s_map; SMFICTX *d_ctx; // for local use only public: typedef size_t callback_set; enum CallBack { CONNECT = 1 << 0, HELO = 1 << 1, SENDER = 1 << 2, RECIPIENT = 1 << 3, HEADER = 1 << 4, EOH = 1 << 5, BODY = 1 << 6, EOM = 1 << 7, ABORT = 1 << 8, CLOSE = 1 << 9, UNKNOWN = 1 << 10, // version > 2 DATA = 1 << 11, // version > 3 ALL_CALLBACKS = (DATA << 1) - 1 }; typedef unsigned long flag_set; enum Flags { NO_FLAGS = 0L, ADD_HEADERS = SMFIF_ADDHDRS, // filter may add headers ADD_RECIPIENTS = SMFIF_ADDRCPT, // filter may add recipients CHANGE_BODY = SMFIF_CHGBODY, // filter may replace body CHANGE_HEADERS = SMFIF_CHGHDRS, // filter may change/delete // headers DELETE_RECIPIENTS = SMFIF_DELRCPT, // filter may delete recipients QUARANTINE = SMFIF_QUARANTINE, // filter may quarantine // envelope ALL_FLAGS = ADD_HEADERS | ADD_RECIPIENTS | CHANGE_BODY | CHANGE_HEADERS | DELETE_RECIPIENTS | QUARANTINE }; enum Status { ACCEPT = SMFIS_ACCEPT, CONTINUE = SMFIS_CONTINUE, DISCARD = SMFIS_DISCARD, REJECT = SMFIS_REJECT, TEMPFAIL = SMFIS_TEMPFAIL, }; enum Return { FAILURE = MI_FAILURE, SUCCESS = MI_SUCCESS, }; static void initialize(std::string const &name, Milter &milter, callback_set callbacks = CONNECT, flag_set flags = NO_FLAGS); static bool start() { return smfi_main() == MI_SUCCESS; } static void stop() { smfi_stop(); } static std::string const &name() { return s_name; } protected: virtual ~Milter(); // empty virtual sfsistat abort(); bool addHeader(std::string const &hdrName, std::string const &hdrValue) { return smfi_addheader(d_ctx, const_cast(hdrName.c_str()), const_cast(hdrValue.c_str())) == SUCCESS; } // from eom() only // hdr-name: without : // hdr-value: \n and \t ok. bool addRecipient(std::string const &rcptName) { return smfi_addrcpt(d_ctx, const_cast(rcptName.c_str())) == SUCCESS; } virtual sfsistat body(unsigned char *text, size_t length); bool changeHeader(std::string const &hdrName, unsigned headerNr, std::string const &hdrValue) { return smfi_chgheader(d_ctx, const_cast(hdrName.c_str()), headerNr, hdrValue.length() ? const_cast(hdrValue.c_str()) : 0 ) == SUCCESS; } virtual Milter *clone() const = 0; // cloning required virtual sfsistat close(); virtual sfsistat connect(char *hostname, _SOCK_ADDR *hostaddr); #if SMFI_VERSION > 3 virtual sfsistat data(); #endif bool deleteRecipient(std::string const &rcptName) { return smfi_delrcpt(d_ctx, const_cast(rcptName.c_str())) == SUCCESS; } virtual sfsistat eoh(); virtual sfsistat eom(); virtual sfsistat header(char *headerf, char *headerv); virtual sfsistat helo(char *helohost); SMFICTX *id() const { return d_ctx; } bool insertHeader(size_t hdrIdx, std::string const &hdrName, std::string const &hdrValue) { return smfi_insheader(d_ctx, hdrIdx, const_cast(hdrName.c_str()), const_cast(hdrValue.c_str())); } static bool openSocket(bool removeIfTrue = true) { return smfi_opensocket(removeIfTrue) == SUCCESS; } bool quarantine(std::string const &reason) { return smfi_quarantine(d_ctx, const_cast(reason.c_str())) == SUCCESS; } virtual sfsistat recipient(char **argv); bool replaceBody(std::string const &body) { return smfi_replacebody(d_ctx, reinterpret_cast ( const_cast(body.c_str()) ), body.length()) == SUCCESS; } virtual sfsistat sender(char **argv); static bool setBacklog(size_t backlog = 5) { return smfi_setbacklog(backlog) == SUCCESS; } static void setConnection(std::string const &socketName) { smfi_setconn(const_cast(socketName.c_str())); } bool setReply(std::string const &rcode, std::string const &xcode = "", std::string const &msg = "") { return smfi_setreply(d_ctx, const_cast(rcode.c_str()), xcode.length() ? const_cast(xcode.c_str()) : 0, const_cast(msg.c_str())); // rcode: The three-digit (RFC 821/2821) SMTP reply code, as a // null-terminated string. rcode cannot be NULL, and must be a // valid 4XX or 5XX reply code. // xxcode The extended (RFC 1893/2034) reply code. If xcode is // NULL, no extended code is used. Otherwise, xcode must // conform to RFC 1893/2034. // * Values passed to smfi_setreply are not checked for // standards compliance. // * The message parameter should contain only printable // characters, other characters may lead to undefined // behavior. For example, CR or LF will cause the call to // fail, single '%' characters will cause the text to be // ignored (if there really should be a '%' in the string, use // '%%' just like for printf(3)). // * If the reply code (rcode) given is a '4XX' code but // SMFI_REJECT is used for the message, the custom reply is // not used. // * Similarly, if the reply code (rcode) given is a '5XX' // code but SMFI_TEMPFAIL is used for the message, the custom // reply is not used. // Note: in neither of the last two cases an error is returned // to the milter, libmilter silently ignores the reply code. // * If the milter returns SMFI_TEMPFAIL and sets the reply // code to '421', then the SMTP server will terminate the SMTP // session with a 421 error code. } // can't do smfi_setmlreply(ctx, ...) // since there is no smfi_Vsetmlreply(ctx, ...) static void setTimeout(size_t seconds = 7210) { smfi_settimeout(seconds); } char const *symval(std::string const &name) const { return smfi_getsymval(d_ctx, const_cast(name.c_str())); } #if SMFI_VERSION > 2 sfsistat unknown(char const *ptr); #endif bool wait() // from eom() only { return smfi_progress(d_ctx) == SUCCESS; } private: static Milter *install(SMFICTX *ctx); static sfsistat mConnect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr) { return install(ctx)->connect(hostname, hostaddr); } static sfsistat mAbort(SMFICTX *ctx) { return install(ctx)->abort(); } static sfsistat mBody(SMFICTX *ctx, unsigned char *body, size_t len) { return install(ctx)->body(body, len); } static sfsistat mSender(SMFICTX *ctx, char **argv) { return install(ctx)->sender(argv); } static sfsistat mRecipient(SMFICTX *ctx, char **argv) { return install(ctx)->recipient(argv); } static sfsistat mEoh(SMFICTX *ctx) { return install(ctx)->eoh(); } static sfsistat mEom(SMFICTX *ctx) { return install(ctx)->eom(); } static sfsistat mHeader(SMFICTX *ctx, char *headerf, char *headerv) { return install(ctx)->header(headerf, headerv); } static sfsistat mHelo(SMFICTX *ctx, char *helohost) { return install(ctx)->helo(helohost); } static sfsistat mClose(SMFICTX *ctx); #if SMFI_VERSION > 2 static sfsistat mUnknown(SMFICTX *ctx, char const *ptr) { return install(ctx)->unknown(ptr); } #endif /* SMFI_VERSION > 2 */ #if SMFI_VERSION > 3 static sfsistat mData(SMFICTX *ctx) { return install(ctx)->data(); } #endif /* SMFI_VERSION > 3 */ }; } #endif bobcat-3.19.01/milter/connect.cc0000644000175000017500000000015612222611511015332 0ustar frankfrank#include "milter.ih" sfsistat Milter::connect(char *hostname, _SOCK_ADDR *hostaddr) { return CONTINUE; } bobcat-3.19.01/milter/eom.cc0000644000175000017500000000010612222611511014454 0ustar frankfrank#include "milter.ih" sfsistat Milter::eom() { return CONTINUE; } bobcat-3.19.01/milter/unknown.cc0000644000175000017500000000016712222611511015402 0ustar frankfrank#include "milter.ih" #if SMFI_VERSION > 2 sfsistat Milter::unknown(char const *ptr) { return CONTINUE; } #endif bobcat-3.19.01/milter/initialize.cc0000644000175000017500000000506012222611511016041 0ustar frankfrank#include "milter.ih" void Milter::initialize(string const &name, Milter &milter, callback_set callbacks, flag_set flags) { if (s_mp) throw Exception(1) << "Milter::initialize(): can't define multiple Milters"; if (flags & ~ALL_FLAGS) throw Exception(1) << "Milter::initialize(): invalid flag(s): " << hex << (flags & ~ALL_FLAGS)<< dec; if (!callbacks) throw Exception(1) << "Milter::initialize(): no callbacks requested"; if (callbacks & ~ALL_CALLBACKS) throw Exception(1) << "Milter::initialize(): illegal callback(s) requested: " << hex << (callbacks & ~ALL_CALLBACKS) << dec; struct smfiDesc descr = {const_cast(name.c_str()), SMFI_VERSION, flags, 0}; s_name = name; s_mp = &milter; s_callClose = callbacks & CLOSE; // Milter has its own close // function callbacks |= CLOSE; // always call mClose() for (size_t callback = 1; callback & ALL_CALLBACKS; callback <<= 1) { switch (callback & callbacks) { case CONNECT: descr.xxfi_connect = &mConnect; break; case HELO: descr.xxfi_helo = &mHelo; break; case SENDER: descr.xxfi_envfrom = &mSender; break; case RECIPIENT: descr.xxfi_envrcpt = &mRecipient; break; case HEADER: descr.xxfi_header = &mHeader; break; case EOH: descr.xxfi_eoh = &mEoh; break; case BODY: descr.xxfi_body = &mBody; break; case EOM: descr.xxfi_eom = &mEom; break; case ABORT: descr.xxfi_abort = &mAbort; break; case CLOSE: descr.xxfi_close = &mClose; break; #if SMFI_VERSION > 2 case UNKNOWN: descr.xxfi_unknown = &mUnknown; break; #endif /* SMFI_VERSION > 2 */ #if SMFI_VERSION > 3 case DATA: descr.xxfi_data = &mData; break; #endif /* SMFI_VERSION > 3 */ } } if (smfi_register(descr) == MI_FAILURE) throw Exception() << "Milter::initialize(): defining Milter " << s_name << " failed"; } bobcat-3.19.01/milter/milter.ih0000644000175000017500000000013312222576524015221 0ustar frankfrank#include "milter" #include using namespace std; using namespace FBB; bobcat-3.19.01/milter/helo.cc0000644000175000017500000000012512222611511014624 0ustar frankfrank#include "milter.ih" sfsistat Milter::helo(char *helohost) { return CONTINUE; } bobcat-3.19.01/milter/header.cc0000644000175000017500000000014512222611511015127 0ustar frankfrank#include "milter.ih" sfsistat Milter::header(char *headerf, char *headerv) { return CONTINUE; } bobcat-3.19.01/milter/data.cc0000644000175000017500000000022112222611511014603 0ustar frankfrank#include "milter.ih" string Milter::s_name; Milter *Milter::s_mp; bool Milter::s_callClose; unordered_map Milter::s_map; bobcat-3.19.01/milter/datamember.cc0000644000175000017500000000014512222611511016000 0ustar frankfrank#include "milter.ih" #if SMFI_VERSION > 3 sfsistat Milter::data() { return CONTINUE; } #endif bobcat-3.19.01/milter/body.cc0000644000175000017500000000015112222611511014631 0ustar frankfrank#include "milter.ih" sfsistat Milter::body(unsigned char *text, size_t length) { return CONTINUE; } bobcat-3.19.01/milter/abort.cc0000644000175000017500000000011012222611511014776 0ustar frankfrank#include "milter.ih" sfsistat Milter::abort() { return CONTINUE; } bobcat-3.19.01/milter/sender.cc0000644000175000017500000000012412222611511015154 0ustar frankfrank#include "milter.ih" sfsistat Milter::sender(char **argv) { return CONTINUE; } bobcat-3.19.01/milter/recipient.cc0000644000175000017500000000012712222611511015661 0ustar frankfrank#include "milter.ih" sfsistat Milter::recipient(char **argv) { return CONTINUE; } bobcat-3.19.01/milter/install.cc0000644000175000017500000000055412222611511015351 0ustar frankfrank#include "milter.ih" Milter *Milter::install(SMFICTX *ctx) { iterator it = s_map.find(ctx); if (it != s_map.end()) // already installed. return it->second; Milter *mp = s_mp->clone(); mp->d_ctx = ctx; // make ctx available to the Milter itself return s_map[ctx] = mp; // return the Milter's address } bobcat-3.19.01/milter/close.cc0000644000175000017500000000011012222611511014774 0ustar frankfrank#include "milter.ih" sfsistat Milter::close() { return CONTINUE; } bobcat-3.19.01/msg/0000755000175000017500000000000012242431634012672 5ustar frankfrankbobcat-3.19.01/msg/showopen.cc0000644000175000017500000000045412222576532015053 0ustar frankfrank#include "msg.ih" #include "../iuo/iuo" void FBB::showOpen() { static bool called = false; if (not called) { called = true; cerr << "[Warning] FBB::Msg::open(...) functions are deprecated.\n" "Use FBB::Errno::open functions instead\n"; } } bobcat-3.19.01/msg/open2.cc0000644000175000017500000000031112222576532014224 0ustar frankfrank#include "msg.ih" void Msg::open(std::ofstream &out, std::string const &name) { showOpen(); out.open(name.c_str()); if (!out) msg() << "Can't write `" << name << "'" << fatal; } bobcat-3.19.01/msg/operatorinsert.cc0000644000175000017500000000016312222576532016266 0ustar frankfrank#include "msg.ih" void operator<<(ostream &ostrstream, void (*manip)(ostream &str)) { (*manip)(ostrstream); } bobcat-3.19.01/msg/linemsg.cc0000644000175000017500000000017112222576532014643 0ustar frankfrank#include "msg.ih" ostringstream &FBB::lineMsg() { msg() << "Line " << Msg::s_line << ": "; return Msg::s_msg; } bobcat-3.19.01/msg/open3.cc0000644000175000017500000000027012222576532014231 0ustar frankfrank#include "msg.ih" void Msg::open(std::ofstream &out, std::string const &name, size_t protection) { showOpen(); close(creat(name.c_str(), protection)); open(out, name); } bobcat-3.19.01/msg/msg0000644000175000017500000000517112222576532013414 0ustar frankfrank#ifndef INCLUDED_BOBCAT_MSG_ #define INCLUDED_BOBCAT_MSG_ #include #include #include #include #include namespace FBB { void info(std::ostream &out); void spool(std::ostream &out); void warning(std::ostream &out); void err(std::ostream &out); void fatal(std::ostream &out); std::ostringstream &msg(); std::ostringstream &lineMsg(); class Msg { friend void err(std::ostream &out); friend void spool(std::ostream &out); friend void info(std::ostream &out); friend void warning(std::ostream &out); friend void fatal(std::ostream &out); friend std::ostringstream &msg(); friend std::ostringstream &msgstream(); friend std::ostringstream &lineMsg(); static size_t s_line; static char const *s_warning; static size_t s_warnCount; static size_t s_count; static size_t s_maxCount; static std::ostringstream s_msg; static std::ostream s_out; static std::ostream s_info; static std::ofstream s_fout; static bool s_display; public: static bool display(); static void open(std::ifstream &in, std::string const &name); static void open(std::ofstream &out, std::string const &name); static void open(std::ofstream &out, std::string const &name, size_t protection); static bool setDisplay(bool mode); static void setOstream(std::string const &name); static void setLine(size_t linenr); static void setWarning(char const *pre = "[Warning] "); static void setMaxCount(size_t maxCount); static size_t count(); static bool errors(); static size_t warnings(); static std::streambuf *setInfoBuf(std::streambuf *newBuffer, bool display = true); static std::streambuf *infoToWarning(); }; inline bool Msg::display() { return s_display; } inline void Msg::setLine(size_t linenr) { s_line = linenr; } inline void Msg::setWarning(char const *pre) { s_warning = pre; } inline void Msg::setMaxCount(size_t maxCount) { s_maxCount = maxCount; } inline size_t Msg::count() { return s_count; } inline bool Msg::errors() { return s_count; } inline size_t Msg::warnings() { return s_warnCount; } inline std::streambuf *Msg::infoToWarning() { return setInfoBuf(s_out.rdbuf()); } inline std::ostringstream &msgstream() { return Msg::s_msg; } } // namespace FBB namespace std { inline void operator<<(ostream &ostrstream, void (*manip)(ostream &str)) { (*manip)(ostrstream); } } #endif bobcat-3.19.01/msg/msg.cc0000644000175000017500000000053712222576532014001 0ustar frankfrank#include "msg.ih" #include "../iuo/iuo" ostringstream &FBB::msg() { static bool called = false; if (not called) { called = true; cerr << "[Warning] FBB::msg() is deprecated.\n" "Use FBB::Mstream objects instead\n"; } Msg::s_msg.clear(); Msg::s_msg.str(""); return Msg::s_msg; } bobcat-3.19.01/msg/open1.cc0000644000175000017500000000034112222576532014226 0ustar frankfrank#include "msg.ih" void Msg::open(std::ifstream &in, std::string const &name) { showOpen(); if (access(name.c_str(), R_OK) != 0) msg() << "Can't read `" << name << "'" << fatal; in.open(name.c_str()); } bobcat-3.19.01/msg/driver/0000755000175000017500000000000012222576533014173 5ustar frankfrankbobcat-3.19.01/msg/driver/build0000755000175000017500000000025212222576533015217 0ustar frankfrank#!/bin/bash CMD="g++ --std=c++0x -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib \ -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/msg/driver/driver.cc0000644000175000017500000000374512222576533016006 0ustar frankfrank#include #include #include #include using namespace FBB; using namespace std; int main(int argc, char **argv) try { cerr << "Any msg stream operational? " << boolalpha << Msg::display() << '\n'; Msg::setDisplay(Msg::INFO, false); // no info msg imsg << "Msg not shown" << endm; Msg::setDisplay(true); // all are shown again imsg << "Info msg" << endm; wmsg << "A warning msg" << endm; emsg << "An error msg" << endm; imsg.reset(wmsg); // info becomes warning imsg << "Info msg as a warning msg" << endm; imsg.reset("info.txt"); // info to info.txt imsg << "Info to info.txt" << endm; imsg.reset(cout); // reset to the original form imsg << "Info msg as an info msg" << endm; fmsg.reset(cerr); Msg::setDisplay(Msg::INFO, false); if (argc == 1) fmsg << "Non-redirectable: need some arguments" << endm; else { Msg::setDisplay(true); imsg << "Thanks for providing " << argc << " arguments " << endm; } string str[] = {"one", "two", "three"}; copy(str, str + sizeof(str) / sizeof(string), ostream_iterator(imsg, " ")); emsg << "This is an error message" << endm; imsg << "This is an informational message" << endm; wmsg << "This is a warning message" << endm; cout << "Enter the name of a non-existing (unreadable) file: "; string fname; getline(cin, fname); try { ifstream in; Msg::open(in, fname); } catch(...) { emsg << fname << " indeed couldn't be read" << endm; } } catch(Errno const &e) { cerr << "Exception: " << (e.which() == fmsg.id() ? "fmsg" : "unknown") << ": " << e.why() << "\n"; msg() << "Got an Errno object, but ignoring it" << err; } bobcat-3.19.01/msg/data.cc0000644000175000017500000000045612222576533014125 0ustar frankfrank#include "msg.ih" char const *Msg::s_warning = "[Warning] "; bool Msg::s_display; size_t Msg::s_line; size_t Msg::s_warnCount; size_t Msg::s_count; size_t Msg::s_maxCount = UINT_MAX; ostringstream Msg::s_msg; ostream Msg::s_out(cout.rdbuf()); ostream Msg::s_info(cout.rdbuf()); ofstream Msg::s_fout; bobcat-3.19.01/msg/setostream.cc0000644000175000017500000000017312222576533015376 0ustar frankfrank#include "msg.ih" void Msg::setOstream(string const &name) { open(s_fout, name); s_out.rdbuf(s_fout.rdbuf()); } bobcat-3.19.01/msg/err.cc0000644000175000017500000000073612222576533014005 0ustar frankfrank#include "msg.ih" void FBB::err(ostream &out) { ostringstream &os = dynamic_cast(out); Msg::s_out << "[Error " << ++Msg::s_count << "] " << os.str() << endl; if (Msg::s_display && Msg::s_out.rdbuf() != Msg::s_info.rdbuf()) Msg::s_info << "[Error " << Msg::s_count << "] " << os.str() << endl; if (Msg::s_count > Msg::s_maxCount) msg() << "More than " << Msg::s_maxCount << " errors encountered." << fatal; } bobcat-3.19.01/msg/warning.cc0000644000175000017500000000052312222576533014654 0ustar frankfrank#include "msg.ih" void FBB::warning(ostream &out) { ++Msg::s_warnCount; ostringstream &os = dynamic_cast(out); Msg::s_out << Msg::s_warning << os.str() << endl; if (!Msg::s_display || Msg::s_out.rdbuf() == Msg::s_info.rdbuf()) return; Msg::s_info << Msg::s_warning << os.str() << endl; } bobcat-3.19.01/msg/info.cc0000644000175000017500000000030112222576533014134 0ustar frankfrank#include "msg.ih" void FBB::info(ostream &out) { if (!Msg::s_display) return; ostringstream &os = dynamic_cast(out); Msg::s_info << os.str() << endl; } bobcat-3.19.01/msg/spool.cc0000644000175000017500000000030312222576533014337 0ustar frankfrank#include "msg.ih" void FBB::spool(ostream &out) { if (!Msg::s_display) return; ostringstream &os = dynamic_cast(out); Msg::s_info << os.str() << flush; } bobcat-3.19.01/msg/setinfobuf.cc0000644000175000017500000000026112222576533015352 0ustar frankfrank#include "msg.ih" streambuf *Msg::setInfoBuf(streambuf *newBuffer, bool display) { s_display = display; return s_info.rdbuf(newBuffer ? newBuffer : s_info.rdbuf()); } bobcat-3.19.01/msg/fatal.cc0000644000175000017500000000027212222576533014277 0ustar frankfrank#include "msg.ih" void FBB::fatal(ostream &out) { ostringstream &os = dynamic_cast(out); Msg::s_out << "[Fatal] " << os.str() << endl; throw Errno(1); } bobcat-3.19.01/msg/setdisplay.cc0000644000175000017500000000017012222576533015366 0ustar frankfrank#include "msg.ih" bool Msg::setDisplay(bool mode) { bool old = s_display; s_display = mode; return old; } bobcat-3.19.01/msg/msg.ih0000644000175000017500000000033712222576533014013 0ustar frankfrank#include "msg" #include #include #include #include #include #include using namespace std; using namespace FBB; namespace FBB { void showOpen(); } bobcat-3.19.01/mstream/0000755000175000017500000000000012242431634013554 5ustar frankfrankbobcat-3.19.01/mstream/mstream1.f0000644000175000017500000000006612223073543015456 0ustar frankfrankinline Mstream::Mstream() : std::ostream(this) {} bobcat-3.19.01/mstream/mstream.ih0000644000175000017500000000020212222576540015544 0ustar frankfrank#include "mstream" #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/mstream/reset1.f0000644000175000017500000000015712223074464015134 0ustar frankfrankinline void Mstream::reset(std::ostream &ostr) { Mbuf::reset(ostr.rdbuf(), maxCount(), tag(), throws()); } bobcat-3.19.01/mstream/isactive.f0000644000175000017500000000007512223073761015536 0ustar frankfrankinline bool Mstream::isActive() const { return good(); } bobcat-3.19.01/mstream/id.f0000644000175000017500000000011512223074105014307 0ustar frankfrankinline long Mstream::id() const { return reinterpret_cast(this); } bobcat-3.19.01/mstream/mstream4.f0000644000175000017500000000031412223073655015461 0ustar frankfrankinline Mstream::Mstream(std::string const &name, size_t maxCount, std::string const &tag, bool throwing) : Mbuf(name, maxCount, tag, throwing), std::ostream(this) {} bobcat-3.19.01/mstream/emsg.cc0000644000175000017500000000016412222576540015023 0ustar frankfrank#include "mstream.ih" namespace FBB { Mstream emsg(std::cout, numeric_limits::max() - 1, "Error"); } bobcat-3.19.01/mstream/reset6.f0000644000175000017500000000026612223074510015132 0ustar frankfrankinline void Mstream::reset(std::streambuf *buf, size_t maxCount, std::string const &tag, bool throwing) { Mbuf::reset(buf, maxCount, tag, throwing); } bobcat-3.19.01/mstream/mstream2.f0000644000175000017500000000031712223073564015461 0ustar frankfrankinline Mstream::Mstream(std::ostream &ostr, size_t maxCount, std::string const &tag, bool throwing) : Mbuf(ostr.rdbuf(), maxCount, tag, throwing), std::ostream(this) {} bobcat-3.19.01/mstream/driver/0000755000175000017500000000000012222576540015053 5ustar frankfrankbobcat-3.19.01/mstream/driver/build0000755000175000017500000000025212222576540016077 0ustar frankfrank#!/bin/bash CMD="g++ --std=c++0x -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib \ -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/mstream/driver/driver.cc0000644000175000017500000000306612222576540016662 0ustar frankfrank#include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { imsg << "Informational: " << endl; imsg.off(); cout << "The i-msg stream is now off. This message should appear once" << endl; imsg << "The i-msg stream is now off. This message should appear once" << endl; imsg << "The i-msg stream is now off. This message should appear once" << endl; cout << "But this message is shown" << endl; wmsg << "Warning message" << endl; emsg << "Oops, this this is an error (not really)" << endl; emsg << "Oops, this goes wrong, too" << endl; imsg.on(); imsg << "And another informational msg: " << emsg.count() << " error messages\n" << flush; emsg << "Third error" << endl; emsg.setMaxCount(3); imsg << "Msg in between" << endl; cerr << "(cerr) LineExcess: " << emsg.lineExcess() << ", count = " << emsg.count() << endl; emsg << "Fourth error" << endl; cerr << "(cerr) LineExcess: " << emsg.lineExcess() << ", count = " << emsg.count() << endl; cerr << "Beyond\n"; } catch(FBB::Errno const &e) { std::cerr << "Got an Errno object: " << e.why() << '\n'; } catch(...) { std::cerr << "Got an exception\n"; } bobcat-3.19.01/mstream/reset3.f0000644000175000017500000000014712223074534015133 0ustar frankfrankinline void Mstream::reset(std::streambuf *buf) { Mbuf::reset(buf, maxCount(), tag(), throws()); } bobcat-3.19.01/mstream/reset5.f0000644000175000017500000000027312223074247015136 0ustar frankfrankinline void Mstream::reset(std::string const &name, size_t maxCount, std::string const &tag, bool throwing) { Mbuf::reset(name, maxCount, tag, throwing); } bobcat-3.19.01/mstream/off.f0000644000175000017500000000007712223074045014477 0ustar frankfrankinline void Mstream::off() { setstate(std::ios::badbit); } bobcat-3.19.01/mstream/flush.cc0000644000175000017500000000063712222576540015216 0ustar frankfrank#include "mstream.ih" namespace FBB { std::ostream &flush(std::ostream &os) { os.flush(); if (Mstream *mp = dynamic_cast(&os)) { if (mp->throws()) throw Exception() << mp->id(); if (mp->lineExcess()) throw Exception() << mp->id() << "Exceeding max. # of " << mp->maxCount() << " messages"; } return os; } } // FBB bobcat-3.19.01/mstream/reset.cc0000644000175000017500000000034012222576540015206 0ustar frankfrank#include "mstream.ih" void Mstream::reset(Mstream const &mstr) { if (Mbuf *mb = dynamic_cast(mstr.rdbuf())) Mbuf::reset(*mb); else throw Exception(1) << "Can't reset Mstream without Mbuf"; } bobcat-3.19.01/mstream/endl.cc0000644000175000017500000000020012222576540015001 0ustar frankfrank#include "mstream.ih" namespace FBB { std::ostream &endl(std::ostream &os) { return FBB::flush(os.put('\n')); } } // FBB bobcat-3.19.01/mstream/imsg.cc0000644000175000017500000000014512222576540015026 0ustar frankfrank#include "mstream.ih" namespace FBB { Mstream imsg(std::cout, numeric_limits::max()); } bobcat-3.19.01/mstream/setactive.cc0000644000175000017500000000021712222576540016056 0ustar frankfrank#include "mstream.ih" bool Mstream::setActive(bool ifTrue) { if (ifTrue) on(); else off(); return ifTrue; } bobcat-3.19.01/mstream/wmsg.cc0000644000175000017500000000016612222576540015047 0ustar frankfrank#include "mstream.ih" namespace FBB { Mstream wmsg(std::cout, numeric_limits::max(), "Warning"); } bobcat-3.19.01/mstream/reset4.f0000644000175000017500000000027612223074423015134 0ustar frankfrankinline void Mstream::reset(std::ostream &ostr, size_t maxCount, std::string const &tag, bool throwing) { Mbuf::reset(ostr.rdbuf(), maxCount, tag, throwing); } bobcat-3.19.01/mstream/reset2.f0000644000175000017500000000015412223074372015130 0ustar frankfrankinline void Mstream::reset(std::string const &name) { Mbuf::reset(name, maxCount(), tag(), throws()); } bobcat-3.19.01/mstream/mstream3.f0000644000175000017500000000030712223073633015456 0ustar frankfrankinline Mstream::Mstream(std::streambuf *buf, size_t maxCount, std::string const &tag, bool throwing) : Mbuf(buf, maxCount, tag, throwing), std::ostream(this) {} bobcat-3.19.01/mstream/mstream0000644000175000017500000001110312223074605015143 0ustar frankfrank#ifndef INCLUDED_BOBCAT_MSTREAM_ #define INCLUDED_BOBCAT_MSTREAM_ #include #include #include #include namespace FBB { std::ostream &endl(std::ostream &os); std::ostream &flush(std::ostream &os); // http://www.drdobbs.com/184401357: // A slightly more serious concern is that the virtual functions in a // class that's derived from streambuf might throw exceptions; // perhaps, for example, a user-defined class for network I/O might // throw an exception when the underlying connection has been // lost. High-level istream and ostream functions will catch those // exceptions and translate them into an error state within the // stream (that’s one of the reasons that seemingly innocent // functions like istream::get are so complicated), but if you’re // working with stream buffers directly there’s nobody to catch // exceptions for you. If you work with stream buffers, you should // make sure that your code is exception safe. class Mstream: private Mbuf, public std::ostream { public: Mstream(); // 1.f initializes to cout explicit Mstream(std::ostream &ostr, // 2.f writes to ostr size_t maxCount = UINT_MAX, std::string const &tag = "", bool throwing = false); explicit Mstream(std::streambuf *buf, // 3.f writes to buf size_t maxCount = UINT_MAX, std::string const &tag = "", bool throwing = false); // uses a named ofstream, explicit Mstream(std::string const &name, // 4.f size_t maxCount = UINT_MAX, std::string const &tag = "", bool throwing = false); // rdbuf members are still available but will turn a Mstream into // the kind of stream the streambuf handles. Except for one if the // reset members below Mstream assumes an Mbuf long id() const; // .f void reset(std::ostream &ostr); // 1.f void reset(std::string const &name); // 2.f void reset(std::streambuf *mbuf); // 3.f void reset(Mstream const &mstream); void reset(std::ostream &ostr, size_t maxCount, // 4.f std::string const &tag, bool throwing); void reset(std::string const &name, size_t maxCount, // 5.f std::string const &tag, bool throwing); // opens the ofstream // and uses that stream for // Mstream's output void reset(std::streambuf *mbuf, size_t maxCount, // 6.f std::string const &tag, bool throwing); void on(); // .f void off(); // .f bool isActive() const; // .f bool setActive(bool ifTrue); using Mbuf::count; // size_t count() const; using Mbuf::lineExcess; // bool lineExcess() const; using Mbuf::lineTag; // string const &lineTag() const; using Mbuf::maxCount; // size_t maxCount() const; using Mbuf::setCount; // void setCount(size_t count); using Mbuf::setLineNr; // void setLineNr(size_t lineNr); using Mbuf::setLineTag; // void setLineTag(string const &lineTag); using Mbuf::setMaxCount; // void setMaxCount(size_t maxCount); using Mbuf::setTag; // void setTag(string const &tag); using Mbuf::tag; // string const &tag() const; using Mbuf::noLineNr; // void noLineNr(); using Mbuf::throws; // bool throws() const; using Mbuf::throwing; // bool throwing(bool ifTrue); }; #include "mstream1.f" #include "mstream2.f" #include "mstream3.f" #include "mstream4.f" #include "id.f" #include "isactive.f" #include "off.f" #include "on.f" #include "reset1.f" #include "reset2.f" #include "reset3.f" #include "reset4.f" #include "reset5.f" #include "reset6.f" extern Mstream emsg; extern Mstream fmsg; extern Mstream imsg; extern Mstream wmsg; } // FBB #endif bobcat-3.19.01/mstream/fmsg.cc0000644000175000017500000000017212222576540015023 0ustar frankfrank#include "mstream.ih" namespace FBB { Mstream fmsg(std::cout, numeric_limits::max(), "Fatal", true); } bobcat-3.19.01/mstream/on.f0000644000175000017500000000005312223074024014330 0ustar frankfrankinline void Mstream::on() { clear(); } bobcat-3.19.01/multistreambuf/0000755000175000017500000000000012242431634015147 5ustar frankfrankbobcat-3.19.01/multistreambuf/stream1.f0000644000175000017500000000015012223074775016676 0ustar frankfrankinline MultiStreambuf::stream::stream(std::ostream &os, Mode mode) : d_os(&os), d_mode(mode) {} bobcat-3.19.01/multistreambuf/ostream.f0000644000175000017500000000011512223075110016755 0ustar frankfrankinline std::ostream &MultiStreambuf::stream::ostream() { return *d_os; } bobcat-3.19.01/multistreambuf/insertstruct.cc0000644000175000017500000000070012222576536020235 0ustar frankfrank#include "multistreambuf.ih" void MultiStreambuf::insertStruct(stream &os, Insert &insert) { switch (os.d_mode) { case ONCE: os.d_mode = RESET; // FALLING THROUGH case ON: os.d_os->write(insert.buffer.data(), insert.buffer.size()).flush(); insert.ok = insert.ok && os.d_os; break; default: break; } } bobcat-3.19.01/multistreambuf/end1.f0000644000175000017500000000012112223075536016143 0ustar frankfrankinline MultiStreambuf::iterator MultiStreambuf::end() { return d_os.end(); } bobcat-3.19.01/multistreambuf/xsputn.cc0000644000175000017500000000023612222576536017031 0ustar frankfrank#include "multistreambuf.ih" std::streamsize MultiStreambuf::xsputn(char const *buffer, std::streamsize n) { d_buffer.append(buffer, n); return n; } bobcat-3.19.01/multistreambuf/multistreambuf1.f0000644000175000017500000000013512223075210020432 0ustar frankfrankinline MultiStreambuf::MultiStreambuf(std::ostream &os, Mode mode) { insert(os, mode); } bobcat-3.19.01/multistreambuf/setmode.f0000644000175000017500000000011612223075024016750 0ustar frankfrankinline void MultiStreambuf::stream::setMode(Mode mode) { d_mode = mode; } bobcat-3.19.01/multistreambuf/mode.f0000644000175000017500000000013012223075065016235 0ustar frankfrankinline MultiStreambuf::Mode MultiStreambuf::stream::mode() const { return d_mode; } bobcat-3.19.01/multistreambuf/end2.f0000644000175000017500000000013512223075657016155 0ustar frankfrankinline MultiStreambuf::const_iterator MultiStreambuf::end() const { return d_os.end(); } bobcat-3.19.01/multistreambuf/begin1.f0000644000175000017500000000012512223075446016465 0ustar frankfrankinline MultiStreambuf::iterator MultiStreambuf::begin() { return d_os.begin(); } bobcat-3.19.01/multistreambuf/insert2.f0000644000175000017500000000017112223075416016704 0ustar frankfrankinline void MultiStreambuf::insert(std::vector const &os) { d_os.insert(d_os.end(), os.begin(), os.end()); } bobcat-3.19.01/multistreambuf/driver/0000755000175000017500000000000012222576536016453 5ustar frankfrankbobcat-3.19.01/multistreambuf/driver/build0000755000175000017500000000025212222576536017477 0ustar frankfrank#!/bin/bash CMD="g++ --std=c++0x -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib \ -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/multistreambuf/driver/driver.cc0000644000175000017500000000106012222576536020252 0ustar frankfrank/* driver.cc */ #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { MultiStreambuf msb(cout); ostream os(&msb); ofstream out("out"); msb.insert(out, MultiStreambuf::ONCE); os << "This is on cout and out" << endl; os << "This is on cout only" << endl; msb.setOnce(); os << "This is on cout and out" << endl; os << "This is on cout only" << endl; return 0; } bobcat-3.19.01/multistreambuf/setonce.cc0000644000175000017500000000017012222576536017125 0ustar frankfrank#include "multistreambuf.ih" void MultiStreambuf::setOnce() { for (auto &os: d_os) stream::setOnce(os); } bobcat-3.19.01/multistreambuf/begin2.f0000644000175000017500000000014112223075642016462 0ustar frankfrankinline MultiStreambuf::const_iterator MultiStreambuf::begin() const { return d_os.begin(); } bobcat-3.19.01/multistreambuf/overflow.cc0000644000175000017500000000023212222576536017327 0ustar frankfrank#include "multistreambuf.ih" int MultiStreambuf::overflow(int c) { if (c == EOF) pSync(); else d_buffer += c; return c; } bobcat-3.19.01/multistreambuf/multistreambuf0000644000175000017500000000530212226240262020132 0ustar frankfrank#ifndef INCLUDED_BOBCAT_MULTISTREAMBUF_ #define INCLUDED_BOBCAT_MULTISTREAMBUF_ #include #include #include #include #include namespace FBB { class MultiStreambuf: public std::streambuf { public: enum Mode { OFF, // stream not used ON, // stream always used ONCE, // stream used until flushed RESET, // stream once used. Set to ONCE to re-use }; class stream // holds a pointer to a stream and a indicator { // telling us whether or not to use the stream friend class MultiStreambuf; std::ostream *d_os; Mode d_mode; public: stream(std::ostream &os, Mode mode = ON); // 1.f void setMode(Mode mode); // .f Mode mode() const; // .f std::ostream &ostream(); // .f private: static void setOnce(stream &os); // .f }; typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; private: std::string d_buffer; std::vector d_os; public: MultiStreambuf() = default; explicit MultiStreambuf(std::ostream &os, Mode mode = ON); // 1.f explicit MultiStreambuf(std::vector const &osvector); // 2.f void insert(std::ostream &os, Mode mode = ON); // 1.f void insert(std::vector const &os); // 2.f iterator begin(); // 1.f iterator end(); // 1.f const_iterator begin() const; // 2.f const_iterator end() const; // 2.f void setOnce(); // reset all `RESET' modes to `ONCE' protected: int pSync(); private: virtual int overflow(int c); virtual std::streamsize xsputn(char const *buffer, std::streamsize n); virtual int sync(); struct Insert; static void insertStruct(stream &os, Insert &insert); }; #include "mode.f" #include "ostream.f" #include "setmode.f" #include "setonce.f" #include "stream1.f" #include "multistreambuf1.f" #include "multistreambuf2.f" #include "begin1.f" #include "begin2.f" #include "end1.f" #include "end2.f" #include "insert1.f" #include "insert2.f" } // namespace FBB #endif bobcat-3.19.01/multistreambuf/multistreambuf.ih0000644000175000017500000000022012226240260020521 0ustar frankfrank#include "multistreambuf" #include using namespace FBB; struct MultiStreambuf::Insert { std::string &buffer; bool ok; }; bobcat-3.19.01/multistreambuf/setonce.f0000644000175000017500000000016212223075152016753 0ustar frankfrankinline void MultiStreambuf::stream::setOnce(stream &os) { if (os.d_mode == RESET) os.d_mode = ONCE; } bobcat-3.19.01/multistreambuf/insert1.f0000644000175000017500000000015212223075334016701 0ustar frankfrankinline void MultiStreambuf::insert(std::ostream &os, Mode mode) { d_os.push_back(stream(os, mode)); } bobcat-3.19.01/multistreambuf/psync.cc0000644000175000017500000000041012222576536016616 0ustar frankfrank#include "multistreambuf.ih" int MultiStreambuf::pSync() { if (!d_buffer.length()) return 0; Insert istruct = {d_buffer, true}; for (auto &os: d_os) insertStruct(os, istruct); d_buffer.erase(); return istruct.ok ? 0 : 1; } bobcat-3.19.01/multistreambuf/sync.cc0000644000175000017500000000012212222576536016436 0ustar frankfrank#include "multistreambuf.ih" int MultiStreambuf::sync() { return pSync(); } bobcat-3.19.01/multistreambuf/multistreambuf2.f0000644000175000017500000000014512223075275020447 0ustar frankfrankinline MultiStreambuf::MultiStreambuf(std::vector const &osvector) { insert(osvector); } bobcat-3.19.01/ofdstream/0000755000175000017500000000000012223320321014055 5ustar frankfrankbobcat-3.19.01/ofdstream/ofdstream1.f0000644000175000017500000000014312223320321016267 0ustar frankfrankinline OFdStream::OFdStream(int fd, size_t n) : OFdStreambuf(fd, n), std::ostream(this) {} bobcat-3.19.01/ofdstream/ofdstream0000644000175000017500000000047012223320321015765 0ustar frankfrank#ifndef INCLUDED_BOBCAT_OFDSTREAM_ #define INCLUDED_BOBCAT_OFDSTREAM_ #include #include namespace FBB { class OFdStream: private OFdStreambuf, public std::ostream { public: explicit OFdStream(int fd, size_t n = 1); }; #include "ofdstream1.f" } // FBB #endif bobcat-3.19.01/ofdstreambuf/0000755000175000017500000000000012242431634014565 5ustar frankfrankbobcat-3.19.01/ofdstreambuf/destructor.cc0000644000175000017500000000012412222576534017276 0ustar frankfrank#include "ofdstreambuf.ih" OFdStreambuf::~OFdStreambuf() { cleanup(d_mode); } bobcat-3.19.01/ofdstreambuf/ofdstreambuf2.cc0000644000175000017500000000020412222576534017642 0ustar frankfrank#include "ofdstreambuf.ih" OFdStreambuf::OFdStreambuf(Mode mode) : d_mode(mode), d_n(0), d_fd(-1), d_buffer(0) {} bobcat-3.19.01/ofdstreambuf/open.f0000644000175000017500000000011612223320321015660 0ustar frankfrankinline void OFdStreambuf::open(int fd, size_t n) { open(fd, d_mode, n); } bobcat-3.19.01/ofdstreambuf/ofdstreambuf3.cc0000644000175000017500000000022112222576534017642 0ustar frankfrank#include "ofdstreambuf.ih" OFdStreambuf::OFdStreambuf(int fd, size_t n) : d_mode(CLOSE_FD), d_buffer(0) { open(fd, CLOSE_FD, n); } bobcat-3.19.01/ofdstreambuf/open.cc0000644000175000017500000000032712222576534016046 0ustar frankfrank#include "ofdstreambuf.ih" void OFdStreambuf::open(int fd, Mode mode, size_t n) { cleanup(mode); d_fd = fd; d_n = (n == 0) ? 1 : n; d_buffer = new char[d_n]; setp(d_buffer, d_buffer + d_n); } bobcat-3.19.01/ofdstreambuf/ofdstreambuf0000644000175000017500000000334312223320321017161 0ustar frankfrank#ifndef INCLUDED_BOBCAT_OFDSTREAMBUF_ #define INCLUDED_BOBCAT_OFDSTREAMBUF_ #include namespace FBB { class OFdStreambuf: public std::streambuf { public: // Mode defines what to do with the file descriptor at // destruction-time or when the default open is // called. CLOSE_FD will close the fd, KEEP_FD will leave the // fd as-is. When open is called with a Mode argument, then // the provided argument is used for the actual fd. The Mode // specified at the constructor is therefore only used for the // mode-less open() call and for the destructor. enum Mode { CLOSE_FD, KEEP_FD, }; private: Mode d_mode; size_t d_n; int d_fd; char *d_buffer; public: OFdStreambuf(); explicit OFdStreambuf(Mode mode); explicit OFdStreambuf(int fd, size_t n = 1); OFdStreambuf(int fd, Mode mode, size_t n = 1); OFdStreambuf(OFdStreambuf const &other) = delete; virtual ~OFdStreambuf(); OFdStreambuf &operator=(OFdStreambuf const &other) = delete; void open(int fd, Mode mode, size_t n = 1); void open(int fd, size_t n = 1); // .f int fd() const; // .f void close(); // .f protected: int pSync(); // .f private: int sync() override; int overflow(int c) override; void cleanup(Mode mode); }; #include "close.f" #include "fd.f" #include "open.f" #include "psync.f" } // FBB #endif bobcat-3.19.01/ofdstreambuf/cleanup.cc0000644000175000017500000000037112222576534016533 0ustar frankfrank#include "ofdstreambuf.ih" void OFdStreambuf::cleanup(Mode mode) { if (d_buffer) { sync(); if (d_mode == CLOSE_FD) ::close(d_fd); delete [] d_buffer; d_buffer = 0; d_fd = -1; } } bobcat-3.19.01/ofdstreambuf/ofdstreambuf1.cc0000644000175000017500000000024312222576534017644 0ustar frankfrank#include "ofdstreambuf.ih" OFdStreambuf::OFdStreambuf() : d_mode(CLOSE_FD), // comply with old default d_n(0), d_fd(-1), d_buffer(0) {} bobcat-3.19.01/ofdstreambuf/ofdstreambuf4.cc0000644000175000017500000000023012222576534017643 0ustar frankfrank#include "ofdstreambuf.ih" OFdStreambuf::OFdStreambuf(int fd, Mode mode, size_t n) : d_mode(mode), d_buffer(0) { open(fd, CLOSE_FD, n); } bobcat-3.19.01/ofdstreambuf/close.f0000644000175000017500000000007512223320321016030 0ustar frankfrankinline void OFdStreambuf::close() { cleanup(CLOSE_FD); } bobcat-3.19.01/ofdstreambuf/overflow.cc0000644000175000017500000000034712222576534016752 0ustar frankfrank#include "ofdstreambuf.ih" int OFdStreambuf::overflow(int c) { sync(); if (c != EOF) { *pptr() = static_cast(c); pbump(1); } return c; } bobcat-3.19.01/ofdstreambuf/psync.f0000644000175000017500000000007012223320321016052 0ustar frankfrankinline int OFdStreambuf::pSync() { return sync(); } bobcat-3.19.01/ofdstreambuf/fd.f0000644000175000017500000000007112223320321015310 0ustar frankfrankinline int OFdStreambuf::fd() const { return d_fd; } bobcat-3.19.01/ofdstreambuf/sync.cc0000644000175000017500000000053312222576534016060 0ustar frankfrank#include "ofdstreambuf.ih" int OFdStreambuf::sync() { if (pptr() > pbase()) { if (write(d_fd, d_buffer, pptr() - pbase()) < 0) std::cerr << "[Warning] OFdStreambuf::sync could not " "write to FD " << d_fd << '\n'; setp(d_buffer, d_buffer + d_n); } return 0; } bobcat-3.19.01/ofdstreambuf/ofdstreambuf.ih0000644000175000017500000000015512222576534017600 0ustar frankfrank#include "ofdstreambuf" #include // #include #include using namespace FBB; bobcat-3.19.01/ofilterstreambuf/0000755000175000017500000000000012242431634015461 5ustar frankfrankbobcat-3.19.01/ofilterstreambuf/ofilterstreambuf2.f0000644000175000017500000000017512223320321021257 0ustar frankfrankinline OFilterStreambuf::OFilterStreambuf(char const *fname, openmode mode) : d_dest(fname, mode), d_out(&d_dest) {} bobcat-3.19.01/ofilterstreambuf/open2.cc0000644000175000017500000000025112222576537017023 0ustar frankfrank#include "ofilterstreambuf.ih" void OFilterStreambuf::open(std::string const &fname, openmode mode) { sync(); d_dest.open(fname, mode); d_out = &d_dest; } bobcat-3.19.01/ofilterstreambuf/destructor.cc0000644000175000017500000000013012222576537020172 0ustar frankfrank#include "ofilterstreambuf.ih" OFilterStreambuf::~OFilterStreambuf() { close(); } bobcat-3.19.01/ofilterstreambuf/open.f0000644000175000017500000000013112223320321016551 0ustar frankfrankinline void OFilterStreambuf::open(std::ostream &out) { close(); d_out = &out; } bobcat-3.19.01/ofilterstreambuf/out.f0000644000175000017500000000011212223320321016416 0ustar frankfrankinline std::ostream &OFilterStreambuf::out() const { return *d_out; } bobcat-3.19.01/ofilterstreambuf/open.cc0000644000175000017500000000024212222576537016741 0ustar frankfrank#include "ofilterstreambuf.ih" void OFilterStreambuf::open(char const *fname, openmode mode) { sync(); d_dest.open(fname, mode); d_out = &d_dest; } bobcat-3.19.01/ofilterstreambuf/ofilterstreambuf1.f0000644000175000017500000000010412223320321021246 0ustar frankfrankinline OFilterStreambuf::OFilterStreambuf() : d_out(&d_dest) {} bobcat-3.19.01/ofilterstreambuf/close.f0000644000175000017500000000011212223320321016714 0ustar frankfrankinline void OFilterStreambuf::close() { sync(); d_dest.close(); } bobcat-3.19.01/ofilterstreambuf/ofilterstreambuf1.cc0000644000175000017500000000023612222576537021441 0ustar frankfrank#include "ofilterstreambuf.ih" OFilterStreambuf::OFilterStreambuf(std::string const &fname, openmode mode) : d_dest(fname, mode), d_out(&d_dest) {} bobcat-3.19.01/ofilterstreambuf/ofilterstreambuf3.f0000644000175000017500000000012212223320321021250 0ustar frankfrankinline OFilterStreambuf::OFilterStreambuf(std::ostream &out) : d_out(&out) {} bobcat-3.19.01/ofilterstreambuf/ofilterstreambuf0000644000175000017500000000231412223320321020746 0ustar frankfrank#ifndef _INCLUDED_OFILTERSTREAMBUF_ #define _INCLUDED_OFILTERSTREAMBUF_ #include #include namespace FBB { class OFilterStreambuf: public std::streambuf { typedef std::ios::openmode openmode; std::ofstream d_dest; std::ostream *d_out; public: OFilterStreambuf(); // 1.f OFilterStreambuf(char const *fname, // 2.f openmode mode = std::ios::out); OFilterStreambuf(std::ostream &out); // 3.f OFilterStreambuf(std::string const &fname, openmode mode = std::ios::out); virtual ~OFilterStreambuf(); void open(char const *fname, openmode mode = std::ios::out); void open(std::string const &fname, openmode mode = std::ios::out); void open(std::ostream &out); // .f void close(); // .f protected: std::ostream &out() const; // .f }; #include "ofilterstreambuf1.f" #include "ofilterstreambuf2.f" #include "ofilterstreambuf3.f" #include "close.f" #include "open.f" #include "out.f" } // FBB #endif bobcat-3.19.01/ofilterstreambuf/ofilterstreambuf.ih0000644000175000017500000000010712222576537021370 0ustar frankfrank#include "ofilterstreambuf" using namespace std; using namespace FBB; bobcat-3.19.01/ofoldstream/0000755000175000017500000000000012242431634014423 5ustar frankfrankbobcat-3.19.01/ofoldstream/settrailingblanks.f0000644000175000017500000000015512223320321020300 0ustar frankfrankinline void OFoldStream::setTrailingBlanks(TrailingBlanks tb) { OFoldStreambuf::setTrailingBlanks(tb); } bobcat-3.19.01/ofoldstream/open2.cc0000644000175000017500000000036612222576532015767 0ustar frankfrank#include "ofoldstream.ih" void OFoldStream::open(ostream &out, size_t leftIndent, size_t rightMargin, TrailingBlanks tb) { OFoldStreambuf::open(out); setMargins(leftIndent, rightMargin); setTrailingBlanks(tb); } bobcat-3.19.01/ofoldstream/setmargins.f0000644000175000017500000000014612223320321016734 0ustar frankfrankinline void OFoldStream::setMargins(size_t lm, size_t rm) { OFoldStreambuf::setMargins(lm, rm); } bobcat-3.19.01/ofoldstream/useblanks.f0000644000175000017500000000011212223320321016540 0ustar frankfrankinline void OFoldStream::useBlanks() { OFoldStreambuf::useBlanks(); } bobcat-3.19.01/ofoldstream/ofoldstream2.f0000644000175000017500000000040012223320321017152 0ustar frankfrankinline OFoldStream::OFoldStream(std::ostream &out, size_t leftIndent, size_t rightMargin, TabsOrBlanks tob, TrailingBlanks tb) : OFoldStreambuf(out, leftIndent, rightMargin, tob, tb), std::ostream(this) {} bobcat-3.19.01/ofoldstream/ofoldstream0000644000175000017500000000424712223320321016661 0ustar frankfrank#ifndef INCLUDED_BOBCAT_OFOLDSTREAM_ #define INCLUDED_BOBCAT_OFOLDSTREAM_ #include #include #include namespace FBB { // 'virtual public OFoldStreambufBlanks is used to avoid 'base class not // accessible' warnings since OFoldStreambuf also inherits from // OFoldStreambufBlanks and only one struct definition is needed in the // final OFoldStream class. class OFoldStream: virtual public OFoldStreambufEnums, private OFoldStreambuf, public std::ostream { public: OFoldStream() = default; explicit OFoldStream(char const *fname, // 1.f size_t leftIndent = 0, size_t rightMargin = 80, TabsOrBlanks tob = BLANKS, TrailingBlanks tb = IGNORE_TRAILING_BLANKS); explicit OFoldStream(std::ostream &dest, // 2.f size_t leftIndent = 0, size_t rightMargin = 80, TabsOrBlanks tob = BLANKS, TrailingBlanks tb = IGNORE_TRAILING_BLANKS); void open(char const *fname, size_t leftIndent = 0, size_t rightMargin = 80, TrailingBlanks tb = IGNORE_TRAILING_BLANKS); void open(std::ostream &out, size_t leftIndent = 0, size_t rightMargin = 80, TrailingBlanks tb = IGNORE_TRAILING_BLANKS); void close(); // .f void setMargins(size_t leftMargin, size_t rightMargin); // .f void setTrailingBlanks(TrailingBlanks tb); // .f void useBlanks(); // .f void useTabs(size_t tabWidth = 8); // .f static size_t leftMargin(std::ostream const &os); // .f static size_t rightMargin(std::ostream const &os); // .f }; #include "ofoldstream1.f" #include "ofoldstream2.f" #include "close.f" #include "leftmargin.f" #include "rightmargin.f" #include "setmargins.f" #include "settrailingblanks.f" #include "useblanks.f" #include "usetabs.f" } // FBB #endif bobcat-3.19.01/ofoldstream/usetabs.f0000644000175000017500000000013512223320321016224 0ustar frankfrankinline void OFoldStream::useTabs(size_t tabWidth) { OFoldStreambuf::useTabs(tabWidth); } bobcat-3.19.01/ofoldstream/leftmargin.f0000644000175000017500000000016512223320321016711 0ustar frankfrankinline size_t OFoldStream::leftMargin(std::ostream const &os) { return OFoldStreambuf::leftMargin(os.rdbuf()); } bobcat-3.19.01/ofoldstream/open1.cc0000644000175000017500000000037512222576532015766 0ustar frankfrank#include "ofoldstream.ih" void OFoldStream::open(char const *fname, size_t leftIndent, size_t rightMargin, TrailingBlanks tb) { OFoldStreambuf::open(fname); setMargins(leftIndent, rightMargin); setTrailingBlanks(tb); } bobcat-3.19.01/ofoldstream/driver/0000755000175000017500000000000012222576532015723 5ustar frankfrankbobcat-3.19.01/ofoldstream/driver/build0000755000175000017500000000007612222576532016753 0ustar frankfrank#!/bin/sh g++ -I../../tmp driver.cc -L../../tmp/lib -lbobcat bobcat-3.19.01/ofoldstream/driver/driver.cc0000644000175000017500000000065412222576532017532 0ustar frankfrank#include #include #include using namespace std; using namespace FBB; void margins(ostream &out) { cout << OFoldStream::leftMargin(out) << ", " << OFoldStream::rightMargin(out) << endl; } int main() { OFoldStream out(cout, 4, 40); out << lm(4); string line; while (getline(cin, line)) out << line << '\n'; margins(out); return 0; } bobcat-3.19.01/ofoldstream/ofoldstream1.f0000644000175000017500000000040212223320321017153 0ustar frankfrankinline OFoldStream::OFoldStream(char const *fname, size_t leftIndent, size_t rightMargin, TabsOrBlanks tob, TrailingBlanks tb) : OFoldStreambuf(fname, leftIndent, rightMargin, tob, tb), std::ostream(this) {} bobcat-3.19.01/ofoldstream/close.f0000644000175000017500000000010212223320321015655 0ustar frankfrankinline void OFoldStream::close() { OFoldStreambuf::close(); } bobcat-3.19.01/ofoldstream/rightmargin.f0000644000175000017500000000016712223320321017076 0ustar frankfrankinline size_t OFoldStream::rightMargin(std::ostream const &os) { return OFoldStreambuf::rightMargin(os.rdbuf()); } bobcat-3.19.01/ofoldstream/ofoldstream.ih0000644000175000017500000000010312222576532017263 0ustar frankfrank#include "ofoldstream" using namespace std; using namespace FBB; bobcat-3.19.01/ofoldstreambuf/0000755000175000017500000000000012242431634015120 5ustar frankfrankbobcat-3.19.01/ofoldstreambuf/indent.cc0000644000175000017500000000060112222576540016711 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::indent(int c) { if (c == '\n') newline(); else if (isspace(c)) { d_ws.assign(d_indent, d_indentChar); d_wsLength += d_indent * d_indentWidth; addWs(c); d_mode = WS; } else if (c != EOF) { d_reqIndent = true; addNonWs(c); d_mode = NON_WS; } } bobcat-3.19.01/ofoldstreambuf/opinsert1.f0000644000175000017500000000014212223320321017175 0ustar frankfrankinline std::ostream &operator<<(std::ostream &out, lm const &idt) { return idt.modify(out); } bobcat-3.19.01/ofoldstreambuf/settrailingblanks.f0000644000175000017500000000020212223320321020766 0ustar frankfrankinline void OFoldStreambuf::setTrailingBlanks(TrailingBlanks tb) { d_handleTrailingBlanks = tb == HANDLE_TRAILING_BLANKS; } bobcat-3.19.01/ofoldstreambuf/indent2.cc0000644000175000017500000000021012222576540016767 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::indent() { for (size_t nr = 0; nr < d_indent; ++nr) put(d_indentChar); } bobcat-3.19.01/ofoldstreambuf/destructor.cc0000644000175000017500000000061612222576540017634 0ustar frankfrank#include "ofoldstreambuf.ih" OFoldStreambuf::~OFoldStreambuf() { s_buffers.erase(findOFoldStreambuf(this)); if (d_mode == NON_WS) flush(); else if (d_mode == WS) { if (d_handleTrailingBlanks) { if (length() <= d_rightMargin) writeWs(); else put('\n'); } } out().rdbuf()->pubsync(); } bobcat-3.19.01/ofoldstreambuf/ws.cc0000644000175000017500000000043312222576540016064 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::ws(int c) { if (c == '\n') { newline(); clearWs(); d_mode = INDENT; } else if (isspace(c)) addWs(c); else if (c != EOF) { addNonWs(c); d_mode = NON_WS; } } bobcat-3.19.01/ofoldstreambuf/useblanks.f0000644000175000017500000000013312223320321017240 0ustar frankfrankinline void OFoldStreambuf::useBlanks() { d_indentChar = ' '; d_indentWidth = 1; } bobcat-3.19.01/ofoldstreambuf/setmargins.cc0000644000175000017500000000024512222576540017610 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::setMargins(size_t leftMargin, size_t rightMargin) { d_rightMargin = rightMargin; d_indent = leftMargin; } bobcat-3.19.01/ofoldstreambuf/iniblankstabs.cc0000644000175000017500000000023612222576540020260 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::iniBlankTabs(TabsOrBlanks tob) { if (tob == BLANKS) useBlanks(); else useTabs(); } bobcat-3.19.01/ofoldstreambuf/findofoldstreambuf.cc0000644000175000017500000000057612222576540021320 0ustar frankfrank#include "ofoldstreambuf.ih" OFoldStreambuf::BufIt OFoldStreambuf::findOFoldStreambuf(streambuf const *buf) { BufIt it = find(s_buffers.begin(), s_buffers.end(), dynamic_cast(buf)); if (it == s_buffers.end()) throw Exception(1) << "Illegal cast from std::streambuf to FBB::OFoldStreambuf"; return it; } bobcat-3.19.01/ofoldstreambuf/usetabs.f0000644000175000017500000000016012223320321016717 0ustar frankfrankinline void OFoldStreambuf::useTabs(size_t tabWidth) { d_indentChar = '\t'; d_indentWidth = tabWidth; } bobcat-3.19.01/ofoldstreambuf/writenonws.f0000644000175000017500000000014612223320321017474 0ustar frankfrankinline void OFoldStreambuf::writeNonWs() const { out().write(d_nonWs.data(), d_nonWs.length()); } bobcat-3.19.01/ofoldstreambuf/leftmargin.f0000644000175000017500000000017712223320321017411 0ustar frankfrankinline size_t OFoldStreambuf::leftMargin(std::streambuf const *buffer) { return (*findOFoldStreambuf(buffer))->d_indent; } bobcat-3.19.01/ofoldstreambuf/put.f0000644000175000017500000000010512223320321016060 0ustar frankfrankinline void OFoldStreambuf::put(int ch) const { out().put(ch); } bobcat-3.19.01/ofoldstreambuf/length.cc0000644000175000017500000000017312222576540016715 0ustar frankfrank#include "ofoldstreambuf.ih" size_t OFoldStreambuf::length() const { return d_next + d_wsLength + d_nonWs.length(); } bobcat-3.19.01/ofoldstreambuf/writews.f0000644000175000017500000000013512223320321016757 0ustar frankfrankinline void OFoldStreambuf::writeWs() const { out().write(d_ws.data(), d_ws.length()); } bobcat-3.19.01/ofoldstreambuf/modify1.f0000644000175000017500000000023212223320321016621 0ustar frankfrankinline std::ostream &lm::modify(std::ostream &out) const { dynamic_cast(*out.rdbuf()).setIndent(d_value); return out; } bobcat-3.19.01/ofoldstreambuf/lm1.f0000644000175000017500000000010112223320321015735 0ustar frankfrankinline lm::lm(int value) : d_value(value < 0 ? 0 : value) {} bobcat-3.19.01/ofoldstreambuf/driver/0000755000175000017500000000000012222576540016417 5ustar frankfrankbobcat-3.19.01/ofoldstreambuf/driver/build0000755000175000017500000000043012222576540017441 0ustar frankfrank#!/bin/bash # (cd ..; icmbuild) || exit 1 # CMD="g++ -o driver -Wall -I../ driver.cc -L../tmp -lofoldstreambuf -L../../tmp/lib -lbobcat -s" # CMD="g++ -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib -lbobcat -s" CMD="g++ -o driver -Wall *.cc -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/ofoldstreambuf/driver/driver.cc0000644000175000017500000000132012222576540020215 0ustar frankfrank#include // #include "../ofoldstreambuf" // #include "../../ofoldstream/ofoldstream" #include using namespace std; using namespace FBB; int main() { // OFoldStreambuf fb(cout, 4, 40); // OFoldStreambuf fb("fsb.out", 4, 40); // ostream out(&fb); OFoldStream out("foldstream.nam2", 4, 40, OFoldStream::TABS); // int c; // int linenr = 0; // while ((c = cin.get()) != EOF) // { // if (c == '\n') // { // if (++linenr == 5) // out << indent(+4); // } // out << static_cast(c); // } out << mlm(-3); string line; while (getline(cin, line)) out << line << '\n'; return 0; } bobcat-3.19.01/ofoldstreambuf/data.cc0000644000175000017500000000013012222576540016336 0ustar frankfrank#include "ofoldstreambuf.ih" vector OFoldStreambuf::s_buffers; bobcat-3.19.01/ofoldstreambuf/modify2.f0000644000175000017500000000023612223320321016626 0ustar frankfrankinline std::ostream &mlm::modify(std::ostream &out) const { dynamic_cast(*out.rdbuf()).modifyIndent(d_value); return out; } bobcat-3.19.01/ofoldstreambuf/rightmargin.f0000644000175000017500000000020512223320321017564 0ustar frankfrankinline size_t OFoldStreambuf::rightMargin(std::streambuf const *buffer) { return (*findOFoldStreambuf(buffer))->d_rightMargin; } bobcat-3.19.01/ofoldstreambuf/overflow.cc0000644000175000017500000000053112222576540017275 0ustar frankfrank#include "ofoldstreambuf.ih" int OFoldStreambuf::overflow(int c) { //cerr << c << ' ' << static_cast(c) << endl; switch (d_mode) { case INDENT: indent(c); break; case WS: ws(c); break; case NON_WS: nonWs(c); break; } return c; } bobcat-3.19.01/ofoldstreambuf/ofoldstreambuf.ih0000644000175000017500000000034012225310017020443 0ustar frankfrank#include "ofoldstreambuf" #include #include #include using namespace std; using namespace FBB; #include "addnonws.f" #include "writews.f" #include "writenonws.f" #include "put.f" bobcat-3.19.01/ofoldstreambuf/nonws.cc0000644000175000017500000000045112222576540016577 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::nonWs(int c) { if (c == '\n') { flush(); newline(); d_mode = INDENT; } else if (isspace(c)) { flush(); addWs(c); d_mode = WS; } else if (c != EOF) addNonWs(c); } bobcat-3.19.01/ofoldstreambuf/mlm1.f0000644000175000017500000000006312223320321016121 0ustar frankfrankinline mlm::mlm(int value) : d_value(value) {} bobcat-3.19.01/ofoldstreambuf/addws.cc0000644000175000017500000000035612222576540016541 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::addWs(int c) { if (c != '\t') ++d_wsLength; else { size_t wsLen = d_next + d_wsLength; d_wsLength = ((wsLen + 8) & ~7) - wsLen; } d_ws += c; } bobcat-3.19.01/ofoldstreambuf/ofoldstreambuf3.cc0000644000175000017500000000073612222576540020540 0ustar frankfrank#include "ofoldstreambuf.ih" OFoldStreambuf::OFoldStreambuf(ostream &stream, size_t indent, size_t rightMargin, TabsOrBlanks tob, TrailingBlanks tb) : OFilterStreambuf(stream), d_rightMargin(rightMargin), d_indent(indent), d_reqIndent(false), d_wsLength(0), d_next(0), d_mode(INDENT), d_handleTrailingBlanks(tb == HANDLE_TRAILING_BLANKS) { s_buffers.push_back(this); iniBlankTabs(tob); } bobcat-3.19.01/ofoldstreambuf/modifyindent.cc0000644000175000017500000000024512222576540020125 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::modifyIndent(int delta) { d_indent += delta; if (static_cast(d_indent) < 0) d_indent = 0; } bobcat-3.19.01/ofoldstreambuf/flush.cc0000644000175000017500000000123112222576540016551 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::flush() { if (d_reqIndent) { d_reqIndent = false; indent(); writeNonWs(); d_next = d_indent + d_nonWs.length(); } else if (length() <= d_rightMargin) { writeWs(); writeNonWs(); d_next += d_wsLength + d_nonWs.length(); } else { newline(); indent(); writeNonWs(); d_next = d_indent + d_nonWs.length(); } // cerr << "FLUSHNONWS " << d_next << ' ' << d_wsLength << ' ' << // d_nonWs.length() << ": " << length() << endl; d_nonWs.erase(); clearWs(); } bobcat-3.19.01/ofoldstreambuf/addnonws.f0000644000175000017500000000010212223320321017062 0ustar frankfrankinline void OFoldStreambuf::addNonWs(int c) { d_nonWs += c; } bobcat-3.19.01/ofoldstreambuf/setindent.f0000644000175000017500000000011312223320321017244 0ustar frankfrankinline void OFoldStreambuf::setIndent(int value) { d_indent = value; } bobcat-3.19.01/ofoldstreambuf/psync.cc0000644000175000017500000000023112222576540016563 0ustar frankfrank#include "ofoldstreambuf.ih" int OFoldStreambuf::pSync() { if (d_mode == NON_WS) flush(); out().rdbuf()->pubsync(); return 0; } bobcat-3.19.01/ofoldstreambuf/opinsert2.f0000644000175000017500000000014312223320321017177 0ustar frankfrankinline std::ostream &operator<<(std::ostream &out, mlm const &idt) { return idt.modify(out); } bobcat-3.19.01/ofoldstreambuf/ofoldstreambuf1.cc0000644000175000017500000000065512222576540020536 0ustar frankfrank#include "ofoldstreambuf.ih" OFoldStreambuf::OFoldStreambuf( size_t indent, size_t rightMargin, TabsOrBlanks tob, TrailingBlanks tb) : d_rightMargin(rightMargin), d_indent(indent), d_reqIndent(false), d_wsLength(0), d_next(0), d_mode(INDENT), d_handleTrailingBlanks(tb == HANDLE_TRAILING_BLANKS) { s_buffers.push_back(this); iniBlankTabs(tob); } bobcat-3.19.01/ofoldstreambuf/ofoldstreambuf2.cc0000644000175000017500000000073512222576540020536 0ustar frankfrank#include "ofoldstreambuf.ih" OFoldStreambuf::OFoldStreambuf(char const *fname, size_t indent, size_t rightMargin, TabsOrBlanks tob, TrailingBlanks tb) : OFilterStreambuf(fname), d_rightMargin(rightMargin), d_indent(indent), d_reqIndent(false), d_wsLength(0), d_next(0), d_mode(INDENT), d_handleTrailingBlanks(tb == HANDLE_TRAILING_BLANKS) { s_buffers.push_back(this); iniBlankTabs(tob); } bobcat-3.19.01/ofoldstreambuf/sync.cc0000644000175000017500000000012112222576540016401 0ustar frankfrank#include "ofoldstreambuf.ih" int OFoldStreambuf::sync() { return pSync(); } bobcat-3.19.01/ofoldstreambuf/clearws.cc0000644000175000017500000000014712222576540017075 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::clearWs() { d_ws.clear(); d_wsLength = 0; } bobcat-3.19.01/ofoldstreambuf/ofoldstreambuf0000644000175000017500000000752212225310012020050 0ustar frankfrank#ifndef INCLUDED_BOBCAT_OFOLDSTREAMBUF_ #define INCLUDED_BOBCAT_OFOLDSTREAMBUF_ #include #include #include #include namespace FBB { class lm { size_t d_value; public: lm(int value); // 1.f std::ostream &modify(std::ostream &out) const; // 1.f }; class mlm { int d_value; public: mlm(int value); // 1.f std::ostream &modify(std::ostream &out) const; // 2.f }; struct OFoldStreambufEnums { enum TrailingBlanks { IGNORE_TRAILING_BLANKS, HANDLE_TRAILING_BLANKS }; enum TabsOrBlanks { BLANKS, TABS }; }; // 'virtual public OFoldStreambufBlanks is used to avoid 'base class not // accessible' warnings when classes inherit from OFoldStreambuf like // OFoldStream. class OFoldStreambuf: virtual public OFoldStreambufEnums, public OFilterStreambuf { friend std::ostream &lm::modify(std::ostream &) const; friend std::ostream &mlm::modify(std::ostream &) const; enum Mode { INDENT, WS, NON_WS }; std::string d_nonWs; std::string d_ws; size_t d_rightMargin; size_t d_indent; bool d_reqIndent; size_t d_wsLength; size_t d_next; Mode d_mode; char d_indentChar; size_t d_indentWidth; bool d_handleTrailingBlanks; typedef std::vector::iterator BufIt; static std::vector s_buffers; public: explicit OFoldStreambuf( size_t leftIndent = 0, size_t rightMargin = 80, TabsOrBlanks tob = BLANKS, TrailingBlanks tb = IGNORE_TRAILING_BLANKS); explicit OFoldStreambuf(char const *fname, size_t leftIndent = 0, size_t rightMargin = 80, TabsOrBlanks tob = BLANKS, TrailingBlanks tb = IGNORE_TRAILING_BLANKS); explicit OFoldStreambuf(std::ostream &stream, size_t leftIndent = 0, size_t rightMargin = 80, TabsOrBlanks tob = BLANKS, TrailingBlanks tb = IGNORE_TRAILING_BLANKS); virtual ~OFoldStreambuf(); void setMargins(size_t leftMargin, size_t rightMargin); void setTrailingBlanks(TrailingBlanks tb); // .f void useBlanks(); // .f void useTabs(size_t tabWidth = 8); // .f static size_t leftMargin(std::streambuf const *buffer); static size_t rightMargin(std::streambuf const *buffer); protected: int pSync(); private: virtual int sync(); virtual int overflow(int c); void indent(int c); void ws(int c); void nonWs(int c); size_t length() const; void iniBlankTabs(TabsOrBlanks tob); void newline(); void addNonWs(int c); // .f void addWs(int c); void indent(); void flush(); void clearWs(); void modifyIndent(int delta); void setIndent(int value); // .f void writeWs() const; // .f void writeNonWs() const; // .f void put(int ch) const; // .f static BufIt findOFoldStreambuf(std::streambuf const *buffer); }; #include "lm1.f" #include "modify1.f" #include "mlm1.f" #include "modify2.f" #include "leftmargin.f" #include "rightmargin.f" #include "setindent.f" #include "settrailingblanks.f" #include "useblanks.f" #include "usetabs.f" // Free functions #include "opinsert1.f" // ostream << lm #include "opinsert2.f" // ostream << mlm } // FBB #endif bobcat-3.19.01/ofoldstreambuf/newline.cc0000644000175000017500000000017412222576540017076 0ustar frankfrank#include "ofoldstreambuf.ih" void OFoldStreambuf::newline() { //cerr << "NEWLINE\n"; put('\n'); d_next = 0; } bobcat-3.19.01/ohexstreambuf/0000755000175000017500000000000012242431634014760 5ustar frankfrankbobcat-3.19.01/ohexstreambuf/destructor.cc0000644000175000017500000000017012222576524017471 0ustar frankfrank#include "ohexstreambuf.ih" OHexStreambuf::~OHexStreambuf() { out().fill(d_padding); out().flags(d_current); } bobcat-3.19.01/ohexstreambuf/ohexstreambuf0000644000175000017500000000153012223320321017543 0ustar frankfrank#ifndef INCLUDED_BOBCAT_OHEXSTREAMBUF_ #define INCLUDED_BOBCAT_OHEXSTREAMBUF_ #include #include namespace FBB { class OHexStreambuf: public OFilterStreambuf { std::ios::fmtflags d_current; char d_padding; size_t d_width; size_t d_count; public: OHexStreambuf(std::ostream &out, size_t width = 0); virtual ~OHexStreambuf(); size_t size() const; // .f static std::string text2bin(std::string const &in); // length and // contents not // checked protected: int pSync(); private: virtual int overflow(int ch); virtual int sync(); }; #include "size.f" } // FBB #endif bobcat-3.19.01/ohexstreambuf/size.f0000644000175000017500000000010212223320321016057 0ustar frankfrankinline size_t OHexStreambuf::size() const { return d_count; } bobcat-3.19.01/ohexstreambuf/overflow.cc0000644000175000017500000000033012222576524017134 0ustar frankfrank#include "ohexstreambuf.ih" int OHexStreambuf::overflow(int ch) { out() << setw(2) << ch; if (d_width && (d_count += 2) >= d_width) { d_count = 0; out() << '\n'; } return ch; } bobcat-3.19.01/ohexstreambuf/ohexstreambuf1.cc0000644000175000017500000000035212222576524020232 0ustar frankfrank#include "ohexstreambuf.ih" OHexStreambuf::OHexStreambuf(std::ostream &out, size_t width) : OFilterStreambuf(out), d_current(out.flags()), d_padding(out.fill('0')), d_width(width), d_count(0) { out << hex; } bobcat-3.19.01/ohexstreambuf/ohexstreambuf.ih0000644000175000017500000000015712222576524020167 0ustar frankfrank#include "ohexstreambuf" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/ohexstreambuf/psync.cc0000644000175000017500000000013612222576524016431 0ustar frankfrank#include "ohexstreambuf.ih" int OHexStreambuf::pSync() { out() << flush; return 0; } bobcat-3.19.01/ohexstreambuf/text2bin.cc0000644000175000017500000000045412222576524017037 0ustar frankfrank#include "ohexstreambuf.ih" string OHexStreambuf::text2bin(string const &in) { string ret; for (size_t idx = 0, end = in.length(); idx != end; idx += 2) { A2x ax(in.substr(idx, 2)); size_t value; ax >> hex >> value; ret += value; } return ret; } bobcat-3.19.01/ohexstreambuf/sync.cc0000644000175000017500000000012012222576524016242 0ustar frankfrank#include "ohexstreambuf.ih" int OHexStreambuf::sync() { return pSync(); } bobcat-3.19.01/onekey/0000755000175000017500000000000012242431634013376 5ustar frankfrankbobcat-3.19.01/onekey/destructor.cc0000644000175000017500000000013412222576535016111 0ustar frankfrank#include "onekey.ih" OneKey::~OneKey() { tcsetattr(STDIN_FILENO, TCSANOW, &d_saved); } bobcat-3.19.01/onekey/get.cc0000644000175000017500000000031212222576535014470 0ustar frankfrank#include "onekey.ih" int OneKey::get() const { int c = cin.get(); // read the char if (d_useEcho) cout << static_cast(c) << flush; return c; } bobcat-3.19.01/onekey/onekey.ih0000644000175000017500000000020412222576535015216 0ustar frankfrank#include "onekey" #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/onekey/setecho.f0000644000175000017500000000011312223320321015157 0ustar frankfrankinline void OneKey::setEcho(Mode state) { d_useEcho = (state == ON); } bobcat-3.19.01/onekey/driver/0000755000175000017500000000000012222576535014701 5ustar frankfrankbobcat-3.19.01/onekey/driver/build0000755000175000017500000000023312222576535015724 0ustar frankfrank#!/bin/bash CMD="g++ -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib -lbobcat -s" # CMD="g++ -o driver -Wall driver.cc -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/onekey/driver/driver.cc0000644000175000017500000000160012222576535016500 0ustar frankfrank/* driver.cc */ #include #include #include using namespace std; using namespace FBB; int main() { try { OneKey onekey; onekey.verify(); cout << "Usage: 1: next chars are echoed, 0: no echo, q: quits\n"; while (true) { char c; cout << "ready...\n"; cout << "Got character '" << (c = onekey.get()) << "'\n"; switch (c) { case '1': onekey.setEcho(OneKey::ON); break; case '0': onekey.setEcho(OneKey::OFF); break; case 'q': return 0; } } } catch (Errno const &e) { cout << e.why() << endl; return e.which(); } } bobcat-3.19.01/onekey/onekey0000644000175000017500000000133612223320321014603 0ustar frankfrank#ifndef INCLUDED_BOBCAT_ONEKEY_ #define INCLUDED_BOBCAT_ONEKEY_ #include namespace FBB { class OneKey { termios d_saved; bool d_useEcho; // default false public: enum Mode { OFF, ON }; explicit OneKey(Mode state = OFF); ~OneKey(); int get() const; // get the next char void setEcho(Mode state); // .f void verify() const; // kept for backward compat. private: OneKey(OneKey const &other) = delete; OneKey const &operator=(OneKey const &other) = delete; }; #include "setecho.f" } // FBB #endif bobcat-3.19.01/onekey/verify.cc0000644000175000017500000000006512222576535015222 0ustar frankfrank#include "onekey.ih" void OneKey::verify() const {} bobcat-3.19.01/onekey/onekey.cc0000644000175000017500000000135012222576535015206 0ustar frankfrank#include "onekey.ih" OneKey::OneKey(Mode state) { setEcho(state); if (!isatty(STDIN_FILENO)) throw Exception(2) << "OneKey::OneKey(): STDIN is not a tty"; if (tcgetattr(STDIN_FILENO, &d_saved)) throw Exception(2) << "OneKey::OneKey(): can't save the current stdin state"; termios tattr; tcgetattr(STDIN_FILENO, &tattr); // can't assign saved to tattr tattr.c_lflag &= ~(ICANON | ECHO); tattr.c_cc[VMIN] = 1; tattr.c_cc[VTIME] = 0; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tattr)) { tcsetattr(STDIN_FILENO, TCSANOW, &d_saved); throw Exception(1) << "OneKey::OneKey(): can't change the stdin state to direct input"; } } bobcat-3.19.01/opstructarray/0000755000175000017500000000000012222577123015030 5ustar frankfrankbobcat-3.19.01/osharedstream/0000755000175000017500000000000012244427062014747 5ustar frankfrankbobcat-3.19.01/osharedstream/open2.cc0000644000175000017500000000025012240161353016270 0ustar frankfrank#include "osharedstream.ih" void OSharedStream::open(int id, std::ios::openmode openMode) { setMemory(SharedMemory(id)); setOpenMode(openMode); clear(); } bobcat-3.19.01/osharedstream/osharedstream3.cc0000644000175000017500000000024212240161231020165 0ustar frankfrank#include "osharedstream.ih" OSharedStream::OSharedStream(size_t id, std::ios::openmode openMode) : SharedStreambuf(id, openMode), std::ostream(this) {} bobcat-3.19.01/osharedstream/meminfo.cc0000644000175000017500000000026512242372327016714 0ustar frankfrank#include "osharedstream.ih" void OSharedStream::memInfo(std::ostream &out, char const *end) const { static_cast(this)->memInfo(out); out << end; } bobcat-3.19.01/osharedstream/open1.cc0000644000175000017500000000041312240161321016263 0ustar frankfrank#include "osharedstream.ih" void OSharedStream::open( size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode, size_t access) { setMemory(SharedMemory(maxSize, sizeUnit, access)); setOpenMode(openMode); clear(); } bobcat-3.19.01/osharedstream/osharedstream2.cc0000644000175000017500000000042112240161176020173 0ustar frankfrank#include "osharedstream.ih" OSharedStream::OSharedStream( size_t maxSize, SharedMemory::SizeUnit sizeUnit, std::ios::openmode openMode, size_t access) : SharedStreambuf(maxSize, sizeUnit, openMode, access), std::ostream(this) {} bobcat-3.19.01/osharedstream/osharedstream1.cc0000644000175000017500000000012512240161121020161 0ustar frankfrank#include "osharedstream.ih" OSharedStream::OSharedStream() : ostream(this) {} bobcat-3.19.01/osharedstream/osharedstream.ih0000644000175000017500000000010412233452430020120 0ustar frankfrank#include "osharedstream" using namespace std; using namespace FBB; bobcat-3.19.01/osharedstream/osharedstream0000644000175000017500000000205212244427062017532 0ustar frankfrank#ifndef INCLUDED_BOBCAT_OSHAREDSTREAM_ #define INCLUDED_BOBCAT_OSHAREDSTREAM_ #include #include namespace FBB { struct OSharedStream: private SharedStreambuf, public std::ostream, public virtual SharedEnum__ { OSharedStream(); OSharedStream( size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::out, size_t access = 0600); OSharedStream( size_t id, std::ios::openmode openMode = std::ios::out | std::ios::in); void open( size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::out, size_t access = 0600); void open( int id, std::ios::openmode openMode = std::ios::in | std::ios::out); using std::ostream::clear; void memInfo(std::ostream &out, char const *end = "\n") const; using SharedStreambuf::id; using SharedStreambuf::remove; using SharedStreambuf::kill; }; } // FBB #endif bobcat-3.19.01/pattern/0000755000175000017500000000000012257325714013570 5ustar frankfrankbobcat-3.19.01/pattern/pattern.ih0000644000175000017500000000544212226237134015566 0ustar frankfrank#include "pattern" /* The PerlSetFSA is a Finite State Automaton converting the special character set characters as used by Perl to their corresponding set-notations. The special perl-set characters may be used inside and outside of character classes. When used in a class, it adds the set to the current set. If the class starts with a caret, then the meaning of the set is reversed: \s <-> \S \d <-> \D (etc). The character sets s, d, and w are currently supported. \b and \B are already part of the standard regex implementation. */ #include #include #include #include #include #include using namespace std; namespace FBB { class PerlSetFSA { class Validator; friend class Validator; enum State { Start, Bs, Set, NegatedSet, SetBs, NestedSet, InsideASet, NegatedSetBs, NegatedNestedSet, InsideANegatedSet, nStates_ }; struct TransitionMatrix { State d_state; int d_input; State d_next; void (PerlSetFSA::*d_action)(); }; static TransitionMatrix s_stateTransitions[]; static TransitionMatrix *s_stateTransitions_end; class Validator { vector d_used; int d_last; State d_state; bool d_valid; size_t d_element; public: Validator() : d_used(nStates_), d_last(0), d_state(nStates_), d_valid(true) {} void operator()(TransitionMatrix const &state); operator bool() const { return d_valid; } }; // s_transition holds as many elements as there are states, // first: points to first element of corresponding state // in s_transition // second: points just beyond the last element of corresponding // state in s_transition typedef pair statePair; static vector s_transition; string d_target; string::iterator d_next; public: //static void setup(); PerlSetFSA(); void convert(string &pattern); private: static void initialize(TransitionMatrix &stateDescription); void nop() {}; void copy(); void copybs(); void w_Set(); void W_Set(); void d_Set(); void D_Set(); void s_Set(); void S_Set(); void w_Nest(); void d_Nest(); void s_Nest(); }; #include "destructor.f" #include "newregex.f" } // FBB using namespace FBB; bobcat-3.19.01/pattern/destroy.cc0000644000175000017500000000027412222576530015567 0ustar frankfrank#include "pattern.ih" void Pattern::destroy() { if (d_regex == 0) return; if (--d_regex->d_referenceCount == 0) delete d_regex; delete [] d_subExpression; } bobcat-3.19.01/pattern/pattern.f0000644000175000017500000000012712223320321015372 0ustar frankfrankinline std::string const &Pattern::pattern() const { return Regex::s_converted; } bobcat-3.19.01/pattern/actions.cc0000644000175000017500000000125712222576530015540 0ustar frankfrank#include "pattern.ih" void PerlSetFSA::copy() { d_target += *d_next; } void PerlSetFSA::copybs() { (d_target += "\\") += *d_next; } void PerlSetFSA::d_Set() { d_target += "[[:digit:]]"; } void PerlSetFSA::s_Set() { d_target += "[[:space:]]"; } void PerlSetFSA::w_Set() { d_target += "[[:alnum:]]"; } void PerlSetFSA::D_Set() { d_target += "[^[:digit:]]"; } void PerlSetFSA::S_Set() { d_target += "[^[:space:]]"; } void PerlSetFSA::W_Set() { d_target += "[^[:alnum:]]"; } void PerlSetFSA::d_Nest() { d_target += "[:digit:]"; } void PerlSetFSA::s_Nest() { d_target += "[:space:]"; } void PerlSetFSA::w_Nest() { d_target += "[:alnum:]"; } bobcat-3.19.01/pattern/destructor.cc0000644000175000017500000000012712223320321016253 0ustar frankfrank#include "pattern.ih" Pattern::~Pattern() { if (d_regex) destroy(); } bobcat-3.19.01/pattern/match.cc0000644000175000017500000000076312222576530015175 0ustar frankfrank#include "pattern.ih" void Pattern::match(string const &text, int options) { int errcode = regexec(&d_regex->d_regex, text.c_str(), d_nSub, d_subExpression, options); if (errcode) throw Exception() << "Pattern::match(): no match"; d_text = text; for (d_beyondLast = d_nSub; d_beyondLast--; ) { if (d_subExpression[d_beyondLast].rm_so != -1) { ++d_beyondLast; return; } } } bobcat-3.19.01/pattern/pattern1.cc0000644000175000017500000000035612223320321015617 0ustar frankfrank#include "pattern.ih" Pattern::Pattern() : d_subExpression(0), d_nSub(0), d_beyondLast(0) { newRegex("\\b", 0); // for the benefit of MACs: \\b prevents } // the `empty subexpression' error. bobcat-3.19.01/pattern/pattern0000644000175000017500000001360512226237121015163 0ustar frankfrank#ifndef INCLUDED_BOBCAT_PATTERN_ #define INCLUDED_BOBCAT_PATTERN_ #include #include // for pair<> #include #include // match() throws an Errno when either the construction (i.e., // compilation of the pattern) or the match failed. // // The 0-index for position() or operator[] indicates the matched text, // other indices indicate subsequent subexpressions // // Patterns may use: // \b - indicating a word-boundary // \d - indicating a digit // \D - indicating no digit // \s - indicating a white-space ([:space:]) char // \S - indicating no white-space ([:space:]) char // // Pattern strings: // // ------------------------------------------------------------ // Required pattern Provide Pattern() Use as argument: // internally with: // ------------------------------------------------------------ // \\ \\\\ \\\\\\\\ | // \d \d \\d | // ------------------------------------------------------------ namespace FBB { class Pattern { typedef std::pair conversion; static conversion s_patmod[]; static size_t s_sizeofPatmod; struct Regex { size_t d_referenceCount; regex_t d_regex; static std::string s_converted; Regex(std::string pattern, int options); ~Regex(); // destructor.f private: Regex(Regex const &other) = delete; Regex &operator=(Regex const &other) = delete; }; Regex *d_regex; regmatch_t *d_subExpression; size_t d_nSub; size_t d_beyondLast; std::string d_text; int d_matchOptions; public: typedef std::pair Position; // define a pattern using a case-flag and number of // ()-subexpressions. Compilation flags: // // REG_EXTENDED // Use POSIX Extended Regular Expression syntax when // interpreting regex. If not set, POSIX Basic Regu­ // lar Expression syntax is used. // // REG_NOSUB // Support for substring addressing of matches is not // required. The nmatch and pmatch parameters to // regexec are ignored if the pattern buffer supplied // was compiled with this flag set. // // REG_NEWLINE // Match-any-character operators don't match a new­ // line. // // A non-matching list ([^...]) not containing a new­ // line does not match a newline. // // Match-beginning-of-line operator (^) matches the // empty string immediately after a newline, regard­ // less of whether eflags, the execution flags of // regexec, contains REG_NOTBOL. // // Match-end-of-line operator ($) matches the empty // string immediately before a newline, regardless of // whether eflags contains REG_NOTEOL. Pattern(); // 1 Pattern(Pattern const &other); // 2.f explicit Pattern(std::string const &pattern, // 3.cc bool caseSensitive = true, size_t nSub = 10, int options = REG_EXTENDED | REG_NEWLINE); Pattern(Pattern &&tmp); // 4 ~Pattern(); Pattern &operator=(Pattern const &other); Pattern &operator=(Pattern &&tmp); Pattern &operator<<(int matchOption); bool operator<<(std::string const &text); void setPattern(std::string const &pattern, bool caseSensitive = true, size_t nSub = 10, int options = REG_EXTENDED | REG_NEWLINE); // match a string with a pattern. true: string matched // options could be: // // REG_NOTBOL // The match-beginning-of-line operator always fails // to match (but see the compilation flag REG_NEWLINE // above) This flag may be used when different por­ // tions of a string are passed to regexec and the // beginning of the string should not be interpreted // as the beginning of the line. // // REG_NOTEOL // The match-end-of-line operator always fails to // match (but see the compilation flag REG_NEWLINE) void match(std::string const &text, int options = 0); std::string before() const; // text before the matched text std::string matched() const; // the matched text .f std::string beyond() const; // text beyond the matched text // (0) is complete matching part. Remaining are subexpressions. // (npos, npos) is returned if index exceeds available indices // (which may be 0) // position of subexpression Position position(size_t index) const; // subexpression itself std::string operator[](size_t index) const; size_t end() const; // index beyond the last available .f std::string const &pattern() const; // compiled pattern void swap(Pattern &other); private: void newRegex(std::string const &pattern, int options); // .f void destroy(); void copy(Pattern const &other); }; #include "pattern2.f" #include "matched.f" #include "pattern.f" #include "end.f" } // FBB #endif bobcat-3.19.01/pattern/operatorassign2.cc0000644000175000017500000000015312222576530017214 0ustar frankfrank#include "pattern.ih" Pattern &Pattern::operator=(Pattern &&tmp) { swap(tmp); return *this; } bobcat-3.19.01/pattern/destructor.f0000644000175000017500000000007312223320321016113 0ustar frankfrankinline Pattern::Regex::~Regex() { regfree(&d_regex); } bobcat-3.19.01/pattern/setpattern.cc0000644000175000017500000000064612222576530016272 0ustar frankfrank#include "pattern.ih" void Pattern::setPattern(string const &pattern, bool caseSensitive, size_t nSub, int options) { delete [] d_subExpression; d_subExpression = new regmatch_t[nSub]; d_nSub = nSub; d_beyondLast = 0; if (--d_regex->d_referenceCount == 0) delete d_regex; newRegex(pattern, options | (caseSensitive ? 0 : REG_ICASE)); d_matchOptions = 0; } bobcat-3.19.01/pattern/operatorlshift1.cc0000644000175000017500000000017712222576530017226 0ustar frankfrank#include "pattern.ih" Pattern &Pattern::operator<<(int matchOptions) { d_matchOptions = matchOptions; return *this; } bobcat-3.19.01/pattern/fsadriver/0000755000175000017500000000000012222576530015551 5ustar frankfrankbobcat-3.19.01/pattern/fsadriver/build0000755000175000017500000004072412222576530016605 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/fsadriver // script generated by the C++ icmake script version 2.12 /* Configurable defines for the build script: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. When defined as an EMPTY STRING, the static library libXXX.a is created: all programs linked to this library will themselves contain the code of the required object modules. This will result in code duplication over different programs linked to this library. When defined as a VERSION STRING, e.g., 1.0.4, a shared library libXXX.so.VERSION is constructed, as well as the links libXXX.so.MAINVERSION and libXXX.so (e.g. 1.0.0 creates libXXX.so.1.0.0, libXXX.so.1 and libXXX.so). Note that with a shared library, the library is always constructed fresh from the compiled object files. But programs linked to this library will SHARE the code stored in the shared library. These programs will therefore tend to be relatively small. Also note that `ldconfig -v' might be required after installing a shared library (libXXX.so) for the first time, so that the linker knows of its existence (in ld.so.cache) BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (default: defined). COMPILER: The compiler to use. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking LOCAL_NAMESPACE:The namespace that you, the programmer, use yourself. QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). USING: List of :-separated namespaces to be used in sources and .ih files, appearing in `using' directives. USING does NOT automatically include LOCAL_NAMESPACE: add your LOCAL_NAMESPACE name to this list if want a `using' directive for your own namespace as well. Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY "" #define BUILD_PROGRAM #define COMPILER "g++" #define COPT "-Wall" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "../.." // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current; // contains name of current dir. int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", interactive, "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD CLASSES = "parser scanner "; if (exists("parser")) // subdir parser exists parser(); if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { printf("\n"); exec(COMPILER, "-o", exe, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef GRAMBUILD "-lfl", #endif #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); #ifdef GRAMBUILD libs += " -lfl"; #endif cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "fsadriver.cc", // program source "fsadriver", // static program library "fsadriver" // binary program ); #else cpp_make ( "", "fsadriver", // static- or so-library "" ); #endif } bobcat-3.19.01/pattern/fsadriver/fsadriver.h0000644000175000017500000000017612222576530017713 0ustar frankfrank#ifndef INCLUDED_FSADRIVER_H_ #define INCLUDED_FSADRIVER_H_ #include #include namespace FBB { } #endif bobcat-3.19.01/pattern/fsadriver/fsadriver.cc0000644000175000017500000000113312222576530020043 0ustar frankfrank/* fsadriver.cc $Id$ $Log$ Revision 1.1 2005/08/19 15:12:52 frank Initial revision Revision 1.1.1.1 2003/04/19 14:24:00 frank Installation of Pattern */ #include "fsadriver.h" #ifndef INCLUDED_PATTERN_H_ #include "../pattern.ih" #endif using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { string line; PerlSetFSA fsa; while (true) { cout << "line to convert: "; if (!getline(cin, line) || line.empty()) break; fsa.convert(line); } return 0; } bobcat-3.19.01/pattern/matched.f0000644000175000017500000000011012223320321015312 0ustar frankfrankinline std::string Pattern::matched() const { return (*this)[0]; } bobcat-3.19.01/pattern/copy.cc0000644000175000017500000000056612222576530015054 0ustar frankfrank#include "pattern.ih" void Pattern::copy(Pattern const &other) { d_regex = other.d_regex; d_regex->d_referenceCount++; d_nSub = other.d_nSub, d_beyondLast =other.d_beyondLast; d_text = other.d_text; d_subExpression = new regmatch_t[d_nSub]; std::copy(other.d_subExpression, other.d_subExpression + d_nSub, d_subExpression); } bobcat-3.19.01/pattern/pattern2.f0000644000175000017500000000010312223320321015446 0ustar frankfrankinline Pattern::Pattern(Pattern const &other) { copy(other); } bobcat-3.19.01/pattern/beyond.cc0000644000175000017500000000025012222576530015350 0ustar frankfrank#include "pattern.ih" string Pattern::beyond() const { size_t begin = d_subExpression[0].rm_eo; return begin < d_text.length() ? d_text.substr(begin) : ""; } bobcat-3.19.01/pattern/driver/0000755000175000017500000000000012222576530015057 5ustar frankfrankbobcat-3.19.01/pattern/driver/build0000755000175000017500000000034012222576530016101 0ustar frankfrank#!/bin/bash tput clear GPP="g++ --std=c++0x" # CMD="$GPP -o driver -Wall -I../ driver.cc ../../errno/*.cc -L../tmp -lpattern -s" CMD="$GPP -o driver -Wall *.cc -lbobcat -s" echo $CMD $CMD || exit 1 echo Ready... driver bobcat-3.19.01/pattern/driver/driver.h0000644000175000017500000000017012222576530016521 0ustar frankfrank#ifndef INCLUDED_DRIVER_H_ #define INCLUDED_DRIVER_H_ #include #include namespace FBB { } #endif bobcat-3.19.01/pattern/driver/driver.cc0000644000175000017500000000567512222576530016676 0ustar frankfrank/* driver.cc */ #include "driver.h" #include using namespace std; using namespace FBB; void showSubstr(string const &str) { static int count = 1; cout << "String " << count++ << " is '" << str << "'\n"; } int main(int argc, char **argv) { { Pattern one("one"); Pattern two(one); Pattern three("a"); Pattern four; three = two; } try { Pattern pattern("aap|noot|mies"); { Pattern extra(Pattern(pattern)); } if (pattern << "noot") cout << "noot matches\n"; else cout << ": noot doesn't match\n"; } catch (exception const &e) { cout << e.what() << ": compilation failed" << endl; } string pat = "\\d+"; while (true) { cout << "Pattern: '" << pat << "'\n"; try { Pattern patt(pat, argc == 1); // case sensitive by default, // any arg for case insensitive cout << "Compiled pattern: " << patt.pattern() << endl; Pattern pattern; pattern = patt; // assignment operator while (true) { cout << "string to match : "; string st; getline(cin, st); if (st == "") break; cout << "String: '" << st << "'\n"; try { pattern.match(st); Pattern p3(pattern); cout << "before: " << p3.before() << "\n" "matched: " << p3.matched() << "\n" "beyond: " << pattern.beyond() << "\n" "end() = " << pattern.end() << endl; for (size_t idx = 0; idx < pattern.end(); ++idx) { string str = pattern[idx]; if (str == "") cout << "part " << idx << " not present\n"; else { Pattern::Position pos = pattern.position(idx); cout << "part " << idx << ": '" << str << "' (" << pos.first << "-" << pos.second << ")\n"; } } } catch (exception const &e) { cout << e.what() << ": " << st << " doesn't match" << endl; continue; } } } catch (exception const &e) { cout << e.what() << ": compilation failed" << endl; } cout << "New pattern: "; if (!getline(cin, pat) || !pat.length()) return 0; } } bobcat-3.19.01/pattern/perlsetfsa.cc0000644000175000017500000000104612222576530016244 0ustar frankfrank#include "pattern.ih" void PerlSetFSA::initialize(TransitionMatrix &stateDescription) { statePair*statePtr = &s_transition[stateDescription.d_state]; if (!statePtr->first) *statePtr = statePair(&stateDescription, &stateDescription); else statePtr->second++; } PerlSetFSA::PerlSetFSA() { if (!s_transition.size()) { s_transition.resize(nStates_); for ( auto &transit: ranger(s_stateTransitions, s_stateTransitions_end) ) initialize(transit); } } bobcat-3.19.01/pattern/data.cc0000644000175000017500000000711512222576530015010 0ustar frankfrank#include "pattern.ih" // Note: all state transitions MUST be clustered per state // the last element of a state cluster is the default transition. // its 0-value will be overwritten by the conversion. // PerlSetFSA::TransitionMatrix PerlSetFSA::s_stateTransitions[] = { {Start, '\\', Bs, &PerlSetFSA::nop }, {Start, '[', Set, &PerlSetFSA::copy }, {Start, 0, Start, &PerlSetFSA::copy }, {Bs, 'd', Start, &PerlSetFSA::d_Set }, {Bs, 's', Start, &PerlSetFSA::s_Set }, {Bs, 'w', Start, &PerlSetFSA::w_Set }, {Bs, 'D', Start, &PerlSetFSA::D_Set }, {Bs, 'S', Start, &PerlSetFSA::S_Set }, {Bs, 'W', Start, &PerlSetFSA::W_Set }, {Bs, 0, Start, &PerlSetFSA::copybs }, {Set, '^', NegatedSet, &PerlSetFSA::copy }, {Set, '\\', SetBs, &PerlSetFSA::nop }, {Set, '[', NestedSet, &PerlSetFSA::copy }, {Set, 0, InsideASet, &PerlSetFSA::copy }, {NegatedSet, '\\', NegatedSetBs, &PerlSetFSA::nop }, {NegatedSet, '[', NegatedNestedSet, &PerlSetFSA::copy }, {NegatedSet, 0, InsideANegatedSet, &PerlSetFSA::copy }, {NegatedSetBs, 'd', NegatedSet, &PerlSetFSA::d_Nest }, {NegatedSetBs, 's', NegatedSet, &PerlSetFSA::s_Nest }, {NegatedSetBs, 'w', NegatedSet, &PerlSetFSA::w_Nest }, {NegatedSetBs, '\\', NegatedSet, &PerlSetFSA::copy }, {NegatedSetBs, ']', Start, &PerlSetFSA::copy }, {NegatedSetBs, 0, NegatedSet, &PerlSetFSA::copybs }, {InsideANegatedSet, ']', Start, &PerlSetFSA::copy }, {InsideANegatedSet, '[', NegatedNestedSet, &PerlSetFSA::copy }, {InsideANegatedSet, '\\', NegatedSetBs, &PerlSetFSA::nop }, {InsideANegatedSet, 0, NegatedNestedSet, &PerlSetFSA::copy }, {NegatedNestedSet, ']', InsideANegatedSet, &PerlSetFSA::copy }, {NegatedNestedSet, 0, NegatedNestedSet, &PerlSetFSA::copy }, {InsideASet, '[', NestedSet, &PerlSetFSA::copy }, {InsideASet, ']', Start, &PerlSetFSA::copy }, {InsideASet, '\\', SetBs, &PerlSetFSA::nop }, {InsideASet, 0, InsideASet, &PerlSetFSA::copy }, {SetBs, 'd', InsideASet, &PerlSetFSA::d_Nest }, {SetBs, 's', InsideASet, &PerlSetFSA::s_Nest }, {SetBs, 'w', InsideASet, &PerlSetFSA::w_Nest }, {SetBs, '\\', InsideASet, &PerlSetFSA::copy }, {SetBs, 0, InsideASet, &PerlSetFSA::copybs }, {NestedSet, ']', InsideASet, &PerlSetFSA::copy }, {NestedSet, 0, NestedSet, &PerlSetFSA::copy }, }; PerlSetFSA::TransitionMatrix *PerlSetFSA::s_stateTransitions_end = PerlSetFSA::s_stateTransitions + sizeof(PerlSetFSA::s_stateTransitions) / sizeof(PerlSetFSA::TransitionMatrix); vector PerlSetFSA::s_transition; string Pattern::Regex::s_converted; bobcat-3.19.01/pattern/regex.cc0000644000175000017500000000120212222576530015200 0ustar frankfrank#include "pattern.ih" Pattern::Regex::Regex(string pattern, int options) : d_referenceCount(1) { PerlSetFSA().convert(pattern); int errcode = regcomp(&d_regex, pattern.c_str(), options); if (errcode) { auto_ptr buffer(new char[100]); regerror(errcode, &d_regex, buffer.get(), 100); throw Exception(errcode) << "Pattern::Pattern(" << pattern << "): " << buffer.get(); } s_converted = pattern; // make the converted pattern available // to who's interested in it. } bobcat-3.19.01/pattern/before.cc0000644000175000017500000000016112222576530015333 0ustar frankfrank#include "pattern.ih" string Pattern::before() const { return d_text.substr(0, d_subExpression[0].rm_so); } bobcat-3.19.01/pattern/validatorobject.cc0000644000175000017500000000142612222576530017252 0ustar frankfrank#include "pattern.ih" void PerlSetFSA::Validator::operator()(TransitionMatrix const &state) { static char name[] = "Pattern::PerlSetFSA::Validator()"; d_element++; if (state.d_state != d_state) // new state ? { if (d_last != 0) d_valid = false, cerr << name << ", element #" << d_element << ": last transition of state " << d_state << " not 0\n"; d_state = state.d_state; // set new state; d_last = state.d_input; // set new transition character if (d_used[d_state]) d_valid = false, cerr << name << ", element #" << d_element << ": Non-contiguous use of state " << d_state << endl; d_used[d_state] = true; } } bobcat-3.19.01/pattern/end.f0000644000175000017500000000010012223320321014452 0ustar frankfrankinline size_t Pattern::end() const { return d_beyondLast; } bobcat-3.19.01/pattern/operatorindex.cc0000644000175000017500000000050112222576530016752 0ustar frankfrank#include "pattern.ih" string Pattern::operator[](size_t index) const { regoff_t begin; return ( index >= d_beyondLast || (begin = d_subExpression[index].rm_so) == -1 ) ? "" : d_text.substr(begin, d_subExpression[index].rm_eo - begin); } bobcat-3.19.01/pattern/swap.cc0000644000175000017500000000013012222576530015037 0ustar frankfrank#include "pattern.ih" void Pattern::swap(Pattern &other) { fswap(*this, other); } bobcat-3.19.01/pattern/operatorlshift2.cc0000644000175000017500000000032512222576530017222 0ustar frankfrank#include "pattern.ih" bool Pattern::operator<<(std::string const &text) try { match(text, d_matchOptions); d_matchOptions = 0; return true; } catch (...) { d_matchOptions = 0; return false; } bobcat-3.19.01/pattern/convert.cc0000644000175000017500000000216012222576530015552 0ustar frankfrank//#include #include "pattern.ih" void PerlSetFSA::convert(string &pattern) { d_next = pattern.begin(); //cerr << "Pattern: " << pattern << endl; d_target.clear(); State state = Start; for ( ; d_next != pattern.end(); d_next++) { int current = *d_next; //cerr << "state: " << setw(2) << state << ", input: " << current << // " (" << static_cast(current) << ") " << // " from: " << (s_transition[state].first - s_stateTransitions) << // ", to: " << (s_transition[state].second - s_stateTransitions) << endl; // set the current char in the transition // matrix s_transition[state].second->d_input = current; TransitionMatrix *mp = s_transition[state].first; while (mp->d_input != current) mp++; // find the appropriate state transition element //cerr << "next state: " << setw(2) << mp->d_next << endl; (this->*mp->d_action)(); // do the appropriate action state = mp->d_next; } pattern = d_target; } bobcat-3.19.01/pattern/pattern3.cc0000644000175000017500000000045712223320321015623 0ustar frankfrank#include "pattern.ih" Pattern::Pattern(string const &pattern, bool caseSensitive, size_t nSub, int options) : d_subExpression(new regmatch_t[nSub]), d_nSub(nSub), d_beyondLast(0), d_matchOptions(0) { newRegex(pattern, options | (caseSensitive ? 0 : REG_ICASE)); } bobcat-3.19.01/pattern/operatorassign.cc0000644000175000017500000000021212222576530017126 0ustar frankfrank#include "pattern.ih" Pattern &Pattern::operator=(Pattern const &other) { Pattern tmp(other); swap(tmp); return *this; } bobcat-3.19.01/pattern/position.cc0000644000175000017500000000053612222576530015743 0ustar frankfrank#include "pattern.ih" Pattern::Position Pattern::position(size_t index) const { regoff_t begin; return ( index >= d_beyondLast || (begin = d_subExpression[index].rm_so) == -1 ) ? Position(string::npos, string::npos) : Position(begin, d_subExpression[index].rm_eo); } bobcat-3.19.01/pattern/newregex.f0000644000175000017500000000016112223320321015537 0ustar frankfrankinline void Pattern::newRegex(string const &pattern, int options) { d_regex = new Regex(pattern, options); } bobcat-3.19.01/pattern/pattern4.cc0000644000175000017500000000042112223320321015613 0ustar frankfrank#include "pattern.ih" Pattern::Pattern(Pattern &&tmp) : d_regex(tmp.d_regex), d_subExpression(tmp.d_subExpression), d_nSub(tmp.d_nSub), d_beyondLast(tmp.d_beyondLast), d_text(tmp.d_text), d_matchOptions(tmp.d_matchOptions) { tmp.d_regex = 0; } bobcat-3.19.01/pf_iterator/0000755000175000017500000000000012257325714014431 5ustar frankfrankbobcat-3.19.01/pf_iterator/destructor.cc0000644000175000017500000000012312222576534017132 0ustar frankfrank#include "../primefactors/primefactors.ih" PrimeFactors::iterator::~iterator() {} bobcat-3.19.01/pf_iterator/iterator2.cc0000644000175000017500000000044612222576534016657 0ustar frankfrank#include "../primefactors/primefactors.ih" PrimeFactors::iterator::iterator(BigIntVector &primes) : d_mode(PRIMES), d_primes(&primes), d_sentinel(1) { if (primes.empty()) primes = BigIntVector{2, 3}; d_lastPrime = primes.back(); d_iterator = primes.begin(); } bobcat-3.19.01/pf_iterator/next.cc0000644000175000017500000000037212222576534015720 0ustar frankfrank#include "../primefactors/primefactors.ih" void PrimeFactors::iterator::next() { do { d_iterator = d_primes->begin(); d_lastPrime += 2; } while (isComposite(d_lastPrime)); d_primes->push_back(d_lastPrime); } bobcat-3.19.01/pf_iterator/checkinitialprimes.cc0000644000175000017500000000046612222576534020615 0ustar frankfrank#include "../primefactors/primefactors.ih" void PrimeFactors::iterator::checkInitialPrimes( BigIntVector const &primes) const { if (primes.size() < 2 || primes[0] != 2 || primes[1] != 3) throw Exception() << "PrimeFactors: first primes must be 2 and 3"; } bobcat-3.19.01/pf_iterator/operatorpreinc.cc0000644000175000017500000000064112222576534017775 0ustar frankfrank#include "../primefactors/primefactors.ih" PrimeFactors::iterator &PrimeFactors::iterator::operatorPreInc() { ++d_iterator; switch (d_mode) { case PRIMES: if (d_iterator != d_primes->cend()) break; d_mode = SENTINEL; d_iterator = d_sentinel.begin(); // FALLING THROUGH case SENTINEL: break; } return *this; } bobcat-3.19.01/pf_iterator/iscomposite.cc0000644000175000017500000000052012222576534017273 0ustar frankfrank#include "../primefactors/primefactors.ih" bool PrimeFactors::iterator::isComposite(BigInt const &candidate) { BigInt last(candidate.isqrtc()); d_sentinel[0] = last + 1; while (*d_iterator <= last) { if ((candidate % *d_iterator).isZero()) return true; ++*this; } return false; } bobcat-3.19.01/pf_iterator/iterator1.cc0000644000175000017500000000014612222576534016653 0ustar frankfrank#include "../primefactors/primefactors.ih" PrimeFactors::iterator::iterator() : d_sentinel(1) {} bobcat-3.19.01/pf_iteratorstream/0000755000175000017500000000000012257325714015645 5ustar frankfrankbobcat-3.19.01/pf_iteratorstream/iteratorstream1.cc0000644000175000017500000000051112222576523021275 0ustar frankfrank#include "../primefactors/primefactors.ih" PrimeFactors::iteratorStream::iteratorStream(std::string const &name, size_t blockSize) : d_name(name), d_blockSize(blockSize) { openStream(); d_stream << hex; d_streamPrimes.reserve(blockSize); resetPrimes(); } bobcat-3.19.01/pf_iteratorstream/destructor.cc0000644000175000017500000000016612222576523020353 0ustar frankfrank#include "../primefactors/primefactors.ih" PrimeFactors::iteratorStream::~iteratorStream() { writeNewPrimes(); } bobcat-3.19.01/pf_iteratorstream/newprimes.OBS0000644000175000017500000000045712222576523020227 0ustar frankfrank#include "../primefactors/primefactors.ih" bool PrimeFactors::iteratorStream::newPrimes() { if (d_newPrimes.empty()) return false; d_primes = d_newPrimes; if (d_newPrimes.size() == d_blockSize) writeNewPrimes(); d_iterator = d_primes.begin(); return true; } bobcat-3.19.01/pf_iteratorstream/resetprimes.cc0000644000175000017500000000066212222576523020520 0ustar frankfrank#include "../primefactors/primefactors.ih" void PrimeFactors::iteratorStream::resetPrimes() { d_stream.clear(); d_stream.seekg(0); d_mode = STREAM_PRIMES; readPrimes(); if (not d_streamPrimes.empty()) checkInitialPrimes(d_streamPrimes); else { d_mode = NEW_PRIMES; d_newPrimes = BigIntVector {2, 3}; d_iterator = d_newPrimes.begin(); d_lastPrime = 3; } } bobcat-3.19.01/pf_iteratorstream/next.cc0000644000175000017500000000054412222576523017133 0ustar frankfrank#include "../primefactors/primefactors.ih" void PrimeFactors::iteratorStream::next() { BigInt candidate = d_lastPrime; do { resetPrimes(); candidate += 2; } while (isComposite(candidate)); if (d_newPrimes.size() == d_blockSize) writeNewPrimes(); d_newPrimes.push_back(d_lastPrime = candidate); } bobcat-3.19.01/pf_iteratorstream/openstream.cc0000644000175000017500000000056712222576523020337 0ustar frankfrank#include "../primefactors/primefactors.ih" void PrimeFactors::iteratorStream::openStream() { User user; if (d_name.find("~/") == 0) d_name.replace(0, 2, user.homedir()); d_stream.open(d_name, ios::in | ios::out); if (not d_stream) { d_stream.clear(); Exception::open(d_stream, d_name, ios::out | ios::trunc | ios::in); } } bobcat-3.19.01/pf_iteratorstream/writenewprimes.cc0000644000175000017500000000045712222576523021244 0ustar frankfrank#include "../primefactors/primefactors.ih" void PrimeFactors::iteratorStream::writeNewPrimes() { d_stream.clear(); d_stream.seekp(0, ios::end); copy(d_newPrimes.begin(), d_newPrimes.end(), ostream_iterator(d_stream, "\n")); d_newPrimes.clear(); } bobcat-3.19.01/pf_iteratorstream/operatorpreinc.cc0000644000175000017500000000136412222576523021212 0ustar frankfrank#include "../primefactors/primefactors.ih" PrimeFactors::iterator &PrimeFactors::iteratorStream::operatorPreInc() { ++d_iterator; switch (d_mode) { case STREAM_PRIMES: if (d_iterator != d_streamPrimes.cend()) break; readPrimes(); if (d_iterator != d_streamPrimes.cend()) break; d_mode = NEW_PRIMES; d_iterator = d_newPrimes.begin(); // FALLING THROUGH case NEW_PRIMES: if (d_iterator != d_newPrimes.cend()) break; d_mode = SENTINEL; d_iterator = d_sentinel.begin(); // FALLING THROUGH case SENTINEL: break; } return *this; } bobcat-3.19.01/pf_iteratorstream/readprimes.cc0000644000175000017500000000065612222576523020314 0ustar frankfrank#include "../primefactors/primefactors.ih" bool PrimeFactors::iteratorStream::readPrimes() { d_streamPrimes.clear(); BigInt tmp; size_t idx; for (idx = 0; idx != d_blockSize; ++idx) { if (not (d_stream >> tmp)) break; d_streamPrimes.push_back(tmp); } if (idx != 0) d_lastPrime = d_streamPrimes.back(); d_iterator = d_streamPrimes.begin(); return idx; } bobcat-3.19.01/pipe/0000755000175000017500000000000012257325714013050 5ustar frankfrankbobcat-3.19.01/pipe/pipe2.cc0000644000175000017500000000015212222576534014374 0ustar frankfrank#include "pipe.ih" Pipe::Pipe(int const *fd) { d_fd[READ] = fd[READ]; d_fd[WRITE] = fd[WRITE]; } bobcat-3.19.01/pipe/readfrom.cc0000644000175000017500000000022712222576534015157 0ustar frankfrank#include "pipe.ih" void Pipe::readFrom(int fd) { close(d_fd[WRITE]); Redirector d(d_fd[READ]); d.swallow(fd); close(d_fd[READ]); } bobcat-3.19.01/pipe/pipe1.cc0000644000175000017500000000017112222576534014374 0ustar frankfrank#include "pipe.ih" Pipe::Pipe() { if (pipe(d_fd)) throw Exception() << "Pipe::Pipe(): " << errnodescr; } bobcat-3.19.01/pipe/writtenby2.cc0000644000175000017500000000035312222576534015471 0ustar frankfrank#include "pipe.ih" void Pipe::writtenBy(int const *fd, size_t n) { close(d_fd[READ]); for (size_t idx = 0; idx < n; ++idx) { Redirector r(d_fd[WRITE]); r.swallow(fd[idx]); } close(d_fd[WRITE]); } bobcat-3.19.01/pipe/readonly.cc0000644000175000017500000000013412222576534015172 0ustar frankfrank#include "pipe.ih" int Pipe::readOnly() { close(d_fd[WRITE]); return d_fd[READ]; } bobcat-3.19.01/pipe/pipe0000644000175000017500000000177412223553726013740 0ustar frankfrank#ifndef INCLUDED_BOBCAT_PIPE_ #define INCLUDED_BOBCAT_PIPE_ #include namespace FBB { class Pipe { protected: enum RW { READ, WRITE }; int d_fd[2]; public: Pipe(); explicit Pipe(int const *fd); // ~Pipe(); removed from the interface as it's implementation was // empty and this class is not a Base class having virtual // members void verify() const; // SF, now empty int readFd() const; // .f int writeFd() const; // .f void readFrom(int filedescriptor); // experimental: void readFrom(int const *filedescriptor, size_t n); int readOnly(); void writtenBy(int filedescriptor); void writtenBy(int const *filedescriptor, size_t n = 2); int writeOnly(); }; #include "readfd.f" #include "writefd.f" } // FBB #endif bobcat-3.19.01/pipe/driver/0000755000175000017500000000000012222576534014343 5ustar frankfrankbobcat-3.19.01/pipe/driver/build0000755000175000017500000000023212222576534015365 0ustar frankfrank#!/bin/bash CMD="g++ -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib -lbobcat -s" #CMD="g++ -o driver -Wall driver.cc -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/pipe/driver/driver.cc0000644000175000017500000000204212222576534016143 0ustar frankfrank#include #include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) try { Pipe p; // construct a pipe cout << "Read file descriptor: " << p.getReadFd() << endl; cout << "Write file descriptor: " << p.getWriteFd() << endl; int pid = fork(); if (pid == -1) return 1; if (!pid) //child { p.readFrom(STDIN_FILENO); // read what goes into the pipe from cin string s; getline(cin, s); cout << "CHILD: Got `" << s << "'" << endl; getline(cin, s); cout << "CHILD: Got `" << s << "'" << endl; return 0; } p.writtenBy(STDOUT_FILENO); // write to the pipe via cout cout << "first line" << endl; cout << "second line" << endl; waitpid(pid, 0, 0); } throw (Errno const &err) { cout << err.why() << endl; return 1; } bobcat-3.19.01/pipe/readfd.f0000644000175000017500000000007312223553704014437 0ustar frankfrankinline int Pipe::readFd() const { return d_fd[READ]; } bobcat-3.19.01/pipe/writtenby.cc0000644000175000017500000000023112222576534015402 0ustar frankfrank#include "pipe.ih" void Pipe::writtenBy(int fd) { close(d_fd[READ]); Redirector d(d_fd[WRITE]); d.swallow(fd); close(d_fd[WRITE]); } bobcat-3.19.01/pipe/writefd.f0000644000175000017500000000007512223553720014656 0ustar frankfrankinline int Pipe::writeFd() const { return d_fd[WRITE]; } bobcat-3.19.01/pipe/verify.cc0000644000175000017500000000006112222576534014660 0ustar frankfrank#include "pipe.ih" void Pipe::verify() const {} bobcat-3.19.01/pipe/readfrom2.cc0000644000175000017500000000035112222576534015237 0ustar frankfrank#include "pipe.ih" void Pipe::readFrom(int const *fd, size_t n) { close(d_fd[WRITE]); for (size_t idx = 0; idx < n; ++idx) { Redirector r(d_fd[READ]); r.swallow(fd[idx]); } close(d_fd[READ]); } bobcat-3.19.01/pipe/writeonly.cc0000644000175000017500000000013512222576534015412 0ustar frankfrank#include "pipe.ih" int Pipe::writeOnly() { close(d_fd[READ]); return d_fd[WRITE]; } bobcat-3.19.01/pipe/pipe.ih0000644000175000017500000000016512222576534014331 0ustar frankfrank#include "pipe" #include #include #include using namespace FBB; bobcat-3.19.01/primefactors/0000755000175000017500000000000012257325714014611 5ustar frankfrankbobcat-3.19.01/primefactors/availableprimes.cc0000644000175000017500000000105312222576532020255 0ustar frankfrank#include "primefactors.ih" void PrimeFactors::availablePrimes() { while (not d_value.isOne()) { BigInt const &prime = **d_iterator; // get the next prime if (prime > d_last) // checked the last available { if (not d_iterator->atSentinel()) { d_factors.push_back({d_value, 1}); d_value = 1; } return; } reduce(prime); // try to reduce d_value by prime ++*d_iterator; } } bobcat-3.19.01/primefactors/setsentinel.f0000644000175000017500000000014412223554365017313 0ustar frankfrankinline void PrimeFactors::iterator::setSentinel(BigInt const &value) { d_sentinel[0] = value; } bobcat-3.19.01/primefactors/primefactors0000644000175000017500000000441212226264673017235 0ustar frankfrank#ifndef INCLUDED_BOBCAT_PRIMEFACTORS_ #define INCLUDED_BOBCAT_PRIMEFACTORS_ #include #include #include #include #include namespace FBB { struct PrimeFactors { struct PrimePower { BigInt prime; size_t power; }; typedef std::vector Factors; private: typedef std::vector BigIntVector; typedef BigIntVector::const_iterator ConstIterator; class iterator { protected: enum InputMode { PRIMES, SENTINEL }; int d_mode; BigIntVector *d_primes; ConstIterator d_iterator; BigInt d_lastPrime; BigIntVector d_sentinel; public: virtual ~iterator(); iterator(); iterator(BigIntVector &primes); // 2 iterator &operator++(); // opinc.f void setSentinel(BigInt const &sentinel); // .f BigInt const &operator*() const; // opstar.f void nextPrime(); // .f BigInt const &lastPrime() const; // .f bool atSentinel() const; // .f protected: void checkInitialPrimes(BigIntVector const &primes) const; bool isComposite(BigInt const &candidate); private: virtual iterator &operatorPreInc(); virtual void next(); }; class iteratorStream; BigInt d_value; BigInt d_last; std::shared_ptr d_iterator; Factors d_factors; public: PrimeFactors(BigIntVector &primes); PrimeFactors(std::string const &name = "", size_t blockSize = 1000); PrimeFactors(PrimeFactors const &other) = delete; Factors const &factorize(BigInt const &value); private: void reduce(BigInt const &prime); void availablePrimes(); void addPrimes(); }; } // FBB #endif bobcat-3.19.01/primefactors/primefactors1.cc0000644000175000017500000000017112222576532017674 0ustar frankfrank#include "primefactors.ih" PrimeFactors::PrimeFactors(BigIntVector &primes) : d_iterator(new iterator(primes)) {} bobcat-3.19.01/primefactors/nextprime.f0000644000175000017500000000010012223554272016756 0ustar frankfrankinline void PrimeFactors::iterator::nextPrime() { next(); } bobcat-3.19.01/primefactors/addprimes.cc0000644000175000017500000000057112222576532017071 0ustar frankfrank#include "primefactors.ih" void PrimeFactors::addPrimes() { BigInt const &prime = d_iterator->lastPrime(); while (not d_value.isOne()) { d_iterator->nextPrime(); if (prime > d_last) // beyond the last possible factor { d_factors.push_back({d_value, 1}); break; } reduce(prime); } } bobcat-3.19.01/primefactors/lastprime.f0000644000175000017500000000013312223554246016752 0ustar frankfrankinline BigInt const &PrimeFactors::iterator::lastPrime() const { return d_lastPrime; } bobcat-3.19.01/primefactors/opstar.f0000644000175000017500000000013312223554147016262 0ustar frankfrankinline BigInt const &PrimeFactors::iterator::operator*() const { return *d_iterator; } bobcat-3.19.01/primefactors/factorize.cc0000644000175000017500000000050112222576532017100 0ustar frankfrank#include "primefactors.ih" PrimeFactors::Factors const &PrimeFactors::factorize(BigInt const &value) { d_factors.clear(); d_value = value; d_last = d_value.isqrtc(); d_iterator->setSentinel(d_last + 1); availablePrimes(); if (not d_value.isOne()) addPrimes(); return d_factors; } bobcat-3.19.01/primefactors/driver/0000755000175000017500000000000012222576532016102 5ustar frankfrankbobcat-3.19.01/primefactors/driver/build0000755000175000017500000000102212222576532017122 0ustar frankfrank#!/bin/bash tput clear LIBS=" -lbobcat" GPP="g++ --std=c++0x" # WHEN LINKING TO A STATIC LIBRARY DON'T FORGET TO LINK AGAINST # ssl (-lssl) # CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp ${LIBS} -lbigint -s" # CMD="$GPP -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib ${LIBS} -s" # CMD="$GPP -o driver -Wall -I../ driver.cc -L../tmp ${LIBS} -s" # CMD="$GPP -o driver -Wall driver.cc ../*.o ../../pf_*/*.o ${LIBS} -s" CMD="$GPP -o driver -Wall *.cc ${LIBS} -s" echo $CMD $CMD || exit 1 echo Ready... driver 4 bobcat-3.19.01/primefactors/driver/driver.cc0000644000175000017500000000137712222576532017714 0ustar frankfrank#include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { PrimeFactors pf1("/tmp/primes"); PrimeFactors::Factors const *factors = &pf1.factorize(stoull(argv[1])); cout << "Using /tmp/primes:\n"; for (auto &factor: *factors) cout << factor.prime << "**" << factor.power << ' '; vector primes; PrimeFactors pf2(primes); factors = &pf2.factorize(stoull(argv[1])); cout << "\n" "Using BigIntVector:\n"; for (auto &factor: *factors) cout << factor.prime << "**" << factor.power << ' '; cout << "\n" "Collected primes: "; for (auto &prime: primes) cout << prime << ' '; cout << '\n'; } bobcat-3.19.01/primefactors/reduce.cc0000644000175000017500000000055312222576532016370 0ustar frankfrank#include "primefactors.ih" void PrimeFactors::reduce(BigInt const &prime) { BigInt remainder; size_t count = 0; while (true) { BigInt div(d_value.divc(&remainder, prime)); if (not remainder.isZero()) break; d_value = div; ++count; } if (count) d_factors.push_back({prime, count}); } bobcat-3.19.01/primefactors/primefactors2.cc0000644000175000017500000000022712222576532017677 0ustar frankfrank#include "primefactors.ih" PrimeFactors::PrimeFactors(string const &name, size_t blockSize) : d_iterator(new iteratorStream(name, blockSize)) {} bobcat-3.19.01/primefactors/atsentinel.f0000644000175000017500000000015012223554337017120 0ustar frankfrankinline bool PrimeFactors::iterator::atSentinel() const { return d_iterator == d_sentinel.begin(); } bobcat-3.19.01/primefactors/primefactors.ih0000644000175000017500000000162012226264761017630 0ustar frankfrank#include "primefactors" #include #include "../exception/exception" //#include #include using namespace std; using namespace FBB; class PrimeFactors::iteratorStream: public iterator { enum InputMode { STREAM_PRIMES, NEW_PRIMES, SENTINEL }; std::string d_name; std::fstream d_stream; size_t d_blockSize; BigIntVector d_streamPrimes; BigIntVector d_newPrimes; public: iteratorStream(std::string const &name, size_t blockSize); ~iteratorStream(); private: iterator &operatorPreInc() override; void next() override; void openStream(); void resetPrimes(); bool readPrimes(); void writeNewPrimes(); }; #include "opinc.f" #include "opstar.f" #include "lastprime.f" #include "nextprime.f" #include "atsentinel.f" #include "setsentinel.f" bobcat-3.19.01/primefactors/opinc.f0000644000175000017500000000014512223554075016065 0ustar frankfrankinline PrimeFactors::iterator &PrimeFactors::iterator::operator++() { return operatorPreInc(); } bobcat-3.19.01/process/0000755000175000017500000000000012260243472013563 5ustar frankfrankbobcat-3.19.01/process/bufsize.cc0000644000175000017500000000013112257522663015544 0ustar frankfrank#include "process.ih" size_t Process::bufSize() const { return d_data->d_bufSize; } bobcat-3.19.01/process/setbufsize.cc0000644000175000017500000000017212257522663016265 0ustar frankfrank#include "process.ih" void Process::setBufSize(size_t bufSize) { d_data->d_bufSize = bufSize == 0 ? 1 : bufSize; } bobcat-3.19.01/process/start1.f0000644000175000017500000000013112257522663015153 0ustar frankfrankinline void Process::start() { start(d_setMode, d_setProcessType, d_setTimeLimit); } bobcat-3.19.01/process/childerrstream.cc0000644000175000017500000000015212257522663017110 0ustar frankfrank#include "process.ih" std::istream &Process::childErrStream() { active(); return d_iChildErr; } bobcat-3.19.01/process/parentprocess.cc0000644000175000017500000000014212257522663016767 0ustar frankfrank#include "process.ih" void Process::parentProcess() // overrides { d_child.pid = pid(); } bobcat-3.19.01/process/operatorfun2.cc0000644000175000017500000000043412257522663016531 0ustar frankfrank#include "process.ih" Process &Process::operator()(IOMode mode, ProcessType type, size_t timeLimit, size_t bufSize) { d_data->d_bufSize = bufSize; d_timeLimit = timeLimit; d_processType = type; sanitizeIOMode(mode); return *this; } bobcat-3.19.01/process/destructor.cc0000644000175000017500000000015712257522663016303 0ustar frankfrank#include "process.ih" Process::~Process() { stop(); delete d_data; // delete additional data } bobcat-3.19.01/process/operatorinsert.cc0000644000175000017500000000047412257522663017167 0ustar frankfrank#include "process.ih" Process &Process::operator<<(std::ostream &(*pf)(std::ostream &)) { if (active()) { if (pf != FBB::eoi) static_cast(*this) << pf; else { close(); waitForChild(); } } return *this; } bobcat-3.19.01/process/settimelimit.f0000644000175000017500000000014612256265017016450 0ustar frankfrankinline void Process::setTimeLimit(size_t timeLimit) { d_setTimeLimit = d_timeLimit = timeLimit; } bobcat-3.19.01/process/opaddis.f0000644000175000017500000000016012256265017015356 0ustar frankfrankinline Process &Process::operator+=(std::string const &command) { d_command += command; return *this; } bobcat-3.19.01/process/showmode.cc0000644000175000017500000000153712257522663015735 0ustar frankfrank#include "process.ih" void Process::showMode(char const *lab) const { std::cerr << lab << ' ' << getpid() << ' ' << d_child.pid << " IOMode: "; if (d_mode == NONE) std::cerr << "NONE "; if (d_mode & CIN) std::cerr << "CIN "; if (d_mode & COUT) std::cerr << "COUT "; if (d_mode & CERR) std::cerr << "CERR "; if (d_mode & IGNORE_COUT) std::cerr << "IGNORE_COUT "; if (d_mode & IGNORE_CERR) std::cerr << "IGNORE_CERR "; if (d_mode & MERGE_COUT_CERR) std::cerr << "MERGE_COUT_CERR "; if (d_mode & DIRECT) std::cerr << "DIRECT "; if (d_setMode & IN_PIPE) std::cerr << "IN_PIPE "; if (d_setMode & OUT_PIPE) std::cerr << "OUT_PIPE "; if (d_setMode & CLOSE_ON_EXEC) std::cerr << "CLOSE_ON_EXEC "; std::cerr << '\n'; } bobcat-3.19.01/process/active.cc0000644000175000017500000000045112257522663015355 0ustar frankfrank#include "process.ih" bool Process::active() { if (d_child.pid != 0) { int retChild = waitpid(d_child.pid, &d_child.ret, WNOHANG); if (retChild == d_child.pid) d_child.pid = 0; // process has ended } return d_child.pid; } bobcat-3.19.01/process/available.cc0000644000175000017500000000015512257021317016011 0ustar frankfrank#include "process.ih" size_t Process::available() { d_selector.setAlarm(0); return whichStream(); } bobcat-3.19.01/process/setprocesstype.f0000644000175000017500000000014712256265017017034 0ustar frankfrankinline void Process::setProcessType(ProcessType type) { d_setProcessType = d_processType = type; } bobcat-3.19.01/process/process4.cc0000644000175000017500000000031612257522663015644 0ustar frankfrank#include "process.ih" Process::Process(size_t mode, ProcessType processType, size_t timeLimit, string const &command) : Process(iomode(mode), processType, timeLimit, 200, command) {} bobcat-3.19.01/process/quotedstring.x0000644000175000017500000000146312222576533016515 0ustar frankfrank#include "process.ih" // On entry, `begin' points at the beginning of the quoted string, on exit, // the quoted string (without the surrounding quotes) is returned, and 'begin' // points to the location immediately following the last quote. // // A single quoted string does not do \-escapes. string Process::quotedString(ConstIter &begin, ConstIter const &end) { string quoted; while (true) { if (++begin == end) throw Exception() << "Process " << d_command << ": unmatched '"; if (*begin == '\'') // stop at the next single quote { ++begin; // skip it return quoted; // and return the string's contents } quoted += *begin; // otherwise add the next char } } bobcat-3.19.01/process/processtype.f0000644000175000017500000000013212256265017016312 0ustar frankfrankinline Process::ProcessType Process::processType() const { return d_setProcessType; } bobcat-3.19.01/process/limiter.cc0000644000175000017500000000225112257522663015547 0ustar frankfrank#include "process.ih" void Process::limiter(Process *process) { size_t &timeLimit = process->d_timeLimit; if (timeLimit == 0) // no timelimit: thread immediately return; // ends unique_lock lock(process->d_data->d_mutex); // get the lock volatile ChildAction &action = process->d_data->d_action; action = TIME_LIMIT; // when the child process ends, signalHandler is called, which // sets d_action to CHILD_ENDED, and notifies this function: // the loop ends with CHILD_ENDED. Otherwise, the time limit is // reached and the wait_for ends with d_action == TIME_LIMIT while (action != CHILD_ENDED) { // When the time limit is reached // the loop breaks, and d_action is // TIME_LIMIT. if (process->d_data->d_condition.wait_for( lock, chrono::seconds(timeLimit)) == cv_status::timeout) break; } if (action == TIME_LIMIT) process->discontinue(process->d_child); } bobcat-3.19.01/process/childredirections.cc0000644000175000017500000000241012257021317017563 0ustar frankfrank#include "process.ih" void Process::childRedirections() { if (d_mode & CIN) // CHILD PROCESS: d_oChildInPipe.readFrom(STDIN_FILENO); // reads from the pipe if (d_mode & MERGE_COUT_CERR) // cout/cerr to 1 pipe { int fd[] = {STDOUT_FILENO, STDERR_FILENO}; d_iChildOutPipe.writtenBy(fd, 2); } else { if (d_mode & COUT) // cout to a pipe d_iChildOutPipe.writtenBy(STDOUT_FILENO); if (d_mode & CERR) // cerr to another pipe d_iChildErrPipe.writtenBy(STDERR_FILENO); if (d_mode & (IGNORE_COUT | IGNORE_CERR)) // ignores cout/cerr { int fd = ::open("/dev/null", O_WRONLY); if (fd == -1) throw Exception() << "Process " << d_command << ": can't open /dev/null"; Redirector redirector(fd); if (d_mode & IGNORE_COUT) // ignores COUT redirector.swallow(Redirector::STDOUT); if (d_mode & IGNORE_CERR) // ignores CERR redirector.swallow(Redirector::STDERR); } } } bobcat-3.19.01/process/process0000644000175000017500000002015112260243466015166 0ustar frankfrank#ifndef INCLUDED_BOBCAT_PROCESS_ #define INCLUDED_BOBCAT_PROCESS_ #include #include #include #include #include #include #include #include #include #include #include #if defined(__FreeBSD_kernel__) || defined(__FreeBSD__) #ifndef BOBCAT_DIY_CLOEXEC_ #define BOBCAT_DIY_CLOEXEC_ #endif #endif namespace FBB { struct ProcessData; struct Process: private Fork, public IOStream, public ProcessEnums { friend Process &operator|(Process &lhs, Process &rhs); enum ProcessType { NO_PATH, USE_PATH, USE_SHELL }; private: bool d_active; IOMode d_mode; size_t d_timeLimit; // seconds allowed to child-process ProcessType d_processType; IOMode d_setMode; // these values are set by the size_t d_setTimeLimit; // set members and used as ProcessType d_setProcessType; // defaults unless overridden by // actual values // Constructors set these values // too. std::string d_command; Pipe d_oChildInPipe; // cin read by the CHILD Pipe d_iChildOutPipe; // cout written by the CHILD Pipe d_iChildErrPipe; // cerr written by the CHILD OFdStreambuf d_oChildInbuf; // Child extracts, IFdStreambuf d_iChildOutbuf; // Child inserts, IFdStreambuf d_iChildErrbuf; // Child inserts std::ostream d_oChildIn; // Parent inserts to child's cin std::istream d_iChildOut; // Parent extracts child's cout std::istream d_iChildErr; // Parent extracts child's cerr Selector d_selector; // senses activities on Child's // out/err streams struct RetPid { int ret; pid_t pid; RetPid(); // 1.f }; RetPid d_child; ProcessData *d_data; char d_notUsed[sizeof(RetPid) - sizeof(ProcessData *)]; #ifdef BOBCAT_DIY_CLOEXEC_ int d_closedByChild = 0; // DIY CLOSE_ON_EXEC #endif public: explicit Process(std::string const &command = ""); // 1 explicit Process(size_t iomode, std::string const &command = ""); // 2 Process(size_t mode, ProcessType type, // 3 std::string const &command = ""); Process(size_t mode, ProcessType type, size_t timeLimit, // 4 std::string const &command = ""); Process(IOMode mode, ProcessType type, size_t timeLimit, // 5 size_t bufSize, std::string const &command = ""); Process(Process const &other) = delete; ~Process() override; // stop()s any ongoing process Process &operator=(Process const &other) = delete; size_t bufSize() const; // returns current buffer size IOMode ioMode() const; // returns default IOMode .f ProcessType processType() const; // returns default ProcessType .f size_t timeLimit() const; // returns default time limit .f void setBufSize(size_t bufSize); void setIOMode(IOMode mode); // change IOMode .f void setProcessType(ProcessType type); // .f void setTimeLimit(size_t timeLimit); // .f // for the next cmd to start // 0 means: no time monitor void setCommand(std::string const &command); // sets cmd, .f Process &operator+=(std::string const &text); // opaddis.f // adds to the command void start(); // 1.f void start(IOMode mode); // 2.f void start(IOMode mode, ProcessType type); // 3.f void start(size_t mode, ProcessType type, size_t timeLimit); // 1 void start(IOMode mode, ProcessType type, // 2 size_t timeLimit, size_t bufSize); void system(); // calls /bin/sh -c cmd; 1.f // shell redirs OK void system(IOMode mode); // 2.f void system(IOMode mode, size_t timeLimit); // 3.f void system(IOMode mode, size_t timeLimit, size_t bufSize); // 4.f int operator=(std::string const &cmd); // sets and starts a command std::string const &str() const; // current command .f template Process &operator<<(Type const &value); // opinsert.f Process &operator<<(std::ostream &(*pf)(std::ostream &)); template Process &operator>>(Type &value); // opextract.f int stop(); // terminate a running childprocess void close(); // closes input to the child void eoi(); // closes input and waits for // the child to end using Fork::waitForChild; bool active(); Process &operator()(IOMode mode); // opfun1.f Process &operator()(IOMode mode, ProcessType type); // opfun2.f // operatorfun1.cc Process &operator()(size_t mode, ProcessType type, size_t timeLimit); Process &operator()(IOMode mode, ProcessType type, // operatorfun2.cc size_t timeLimit, size_t bufSize); std::istream &childErrStream(); // READ cerr from the child std::istream &cerr(); // same, but deprecated std::istream &childOutStream(); // .f // READ cout from the child // (also: direct through // extraction) size_t available(); // returns ChildOutput bit_or // (cf. manpage) void showMode(char const *lab) const; private: void childProcess() override; void childRedirections() override; void parentProcess() override; void parentRedirections() override; void newPipe(Pipe &pipe); pid_t discontinue(RetPid &proc); ChildOutput whichStream(); void close(int fd); void closeWriteFd(Pipe &pipe); void closeReadFd(Pipe &pipe); void rmBackticks(); void forking(); IOMode sanitizeIOMode(IOMode mode); void newPipes(); void closeChildInputOnExec(); typedef std::string::const_iterator ConstIter; struct ExecContext; ExecContext analyzeCommand(); static void limiter(Process *process); }; #include "childoutstream.f" #include "eoi.f" #include "eoi2.f" #include "iomode.f" #include "opaddis.f" #include "opextract.f" #include "opfun1.f" #include "opfun2.f" #include "opinsert.f" #include "processtype.f" #include "setcommand.f" #include "setiomode.f" #include "setprocesstype.f" #include "settimelimit.f" #include "start1.f" #include "start2.f" #include "start3.f" #include "str.f" #include "system1.f" #include "system2.f" #include "system3.f" #include "system4.f" #include "timelimit.f" } // FBB #endif bobcat-3.19.01/process/forking.cc0000644000175000017500000000022612257522663015541 0ustar frankfrank#include "process.ih" void Process::forking() { newPipes(); if (d_mode == IOMode::DIRECT) childProcess(); fork(); } bobcat-3.19.01/process/process2.cc0000644000175000017500000000021212257522663015635 0ustar frankfrank#include "process.ih" Process::Process(size_t mode, std::string const &command) : Process(iomode(mode), NO_PATH, 0, 200, command) {} bobcat-3.19.01/process/newpipes.cc0000644000175000017500000000046112257021317015723 0ustar frankfrank#include "process.ih" void Process::newPipes() { if ((d_setMode & CIN) && not (d_setMode & IN_PIPE)) newPipe(d_oChildInPipe); if ((d_mode & (COUT | MERGE_COUT_CERR))) newPipe(d_iChildOutPipe); if (d_mode & CERR) newPipe(d_iChildErrPipe); } bobcat-3.19.01/process/operatorpipe.cc0000644000175000017500000000372212257522663016617 0ustar frankfrank#include "process.ih" // See ../README.process-pipe for an explanation of the inner workings of // operator| namespace FBB { Process &operator|(Process &lhs, Process &rhs) { // make sure output is available if (not (lhs.d_mode & Process::MERGE_COUT_CERR)) { lhs.d_mode |= Process::COUT; lhs.d_setMode |= Process::COUT; } // all but the first process has IN_PIPE set if ( (lhs.d_setMode & Process::CIN) && not (lhs.d_setMode & Process::IN_PIPE) ) lhs.d_setMode |= Process::CLOSE_ON_EXEC; // This is the output end of the pipe lhs.d_setMode |= Process::PIPES_OK | Process::OUT_PIPE; rhs.d_setMode |= Process::PIPES_OK; lhs.start(); // forking() does the real work #ifdef BOBCAT_DIY_CLOEXEC_ rhs.d_closedByChild = lhs.d_closedByChild; // children close the initial // writing ends of the pipes // to the 1st process #endif rhs.d_oChildInPipe = lhs.d_iChildOutPipe; // copy the input fm the lhs's child to the rhs's // output. lhs.iChildOutPipe only has an open // read-pipe and will be available to the rhs's // child process to read via its stdin, thus // connecting lhs's output to the rhs's input if (lhs.d_oChildIn.rdbuf() != 0) { lhs.d_oChildIn.rdbuf(0); rhs.d_oChildInbuf.open(lhs.d_oChildInbuf.fd(), 200); rhs.d_oChildIn.rdbuf(&rhs.d_oChildInbuf); } // this is the input end of the pipe rhs.d_setMode |= Process::CIN | Process::IN_PIPE; rhs.d_mode |= Process::CIN; return rhs; // to start do, e.g., (p1|p2).start() } } bobcat-3.19.01/process/iomode.f0000644000175000017500000000015612257522663015220 0ustar frankfrankinline Process::IOMode Process::ioMode() const { return d_mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC); } bobcat-3.19.01/process/newpipe.cc0000644000175000017500000000020012257021317015527 0ustar frankfrank#include "process.ih" void Process::newPipe(Pipe &pipe) { closeReadFd(pipe); closeWriteFd(pipe); pipe = Pipe(); } bobcat-3.19.01/process/dquotedstring.x0000644000175000017500000000245712222576533016665 0ustar frankfrank#include "process.ih" // On entry, `begin' points at the beginning of the double quoted string, // on exit, the unescaped double quoted string (without the surrounding double // quotes) is returned, and 'begin' points to the location immediately // following the last double quote. string Process::dquotedString(ConstIter &begin, ConstIter const &end) { string dquoted; while (true) { if (++begin == end) throw Exception() << "Process " << d_command << ": unmatched \""; switch (*begin) { default: // regular characters are added to dquoted dquoted += *begin; break; case '\\': // backslash: accept it and accept the next char dquoted += '\\'; if (begin + 1 == end) // the \ was the last character break; // causing an error at the loop's top dquoted += *++begin; // add the char beyond the \-char break; case '"': // closing double quote observed ++begin; // skip it // return the unescaped double quoted string's return dquoted = String::unescape(dquoted); // contents } } } bobcat-3.19.01/process/str.f0000644000175000017500000000011112256265017014537 0ustar frankfrankinline std::string const &Process::str() const { return d_command; } bobcat-3.19.01/process/start1.cc0000644000175000017500000000022512257522663015317 0ustar frankfrank#include "process.ih" void Process::start(size_t mode, ProcessType type, size_t timeLimit) { start(iomode(mode), type, timeLimit, bufSize()); } bobcat-3.19.01/process/sanitizeiomode.cc0000644000175000017500000000205212257522663017124 0ustar frankfrank#include "process.ih" Process::IOMode Process::sanitizeIOMode(IOMode mode) { if ( not (mode & PIPES_OK) && (mode & (IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC)) ) throw invalid_argument("IOModes IN_PIPE, OUT_PIPE and CLOSE_ON_EXIT " "may not be specified"); if ((mode & DIRECT) && (mode & ~DIRECT)) throw invalid_argument("IOModes cannot be combined with DIRECT"); if ((mode & IGNORE_CERR) && (mode & (CERR | MERGE_COUT_CERR))) throw invalid_argument( "IOMode IGNORE_CERR cannot be used with modes " "CERR or MERGE_COUT_CERR"); if ((mode & IGNORE_COUT) && (mode & (COUT | MERGE_COUT_CERR))) throw invalid_argument( "IOMode IGNORE_COUT cannot be used with modes " "COUT or MERGE_COUT_CERR"); if ((mode & MERGE_COUT_CERR) && (mode & (CERR | COUT))) throw invalid_argument( "IOMode MERGE_COUT_CERR cannot be used with modes COUT or CERR"); return d_mode = mode; } bobcat-3.19.01/process/retpid1.f0000644000175000017500000000007512257021317015302 0ustar frankfrankinline Process::RetPid::RetPid() : ret(0), pid(0) {} bobcat-3.19.01/process/closereadfd.cc0000644000175000017500000000013412257021317016341 0ustar frankfrank#include "process.ih" void Process::closeReadFd(Pipe &pipe) { close(pipe.readFd()); } bobcat-3.19.01/process/analyzecommand.cc0000644000175000017500000000142112256265017017076 0ustar frankfrank#include "process.ih" Process::ExecContext Process::analyzeCommand() { // split the elements in d_command String::Type type; vector elements(String::split(&type, d_command)); if (type != String::NORMAL) throw Exception() << "Process: " << d_command << ": ill-formed"; ExecContext ec = {0, new char const *[elements.size() + 1]}; for (auto str: elements) // copy the elements to ec.args ec.argv[ec.argc++] = (new string(str))->c_str(); // the allocated memory is never returned, but that's OK as the // program's execution ends and the args are passed over to the child // process. ec.argv[ec.argc] = 0; // terminate in a null ptr return ec; } bobcat-3.19.01/process/process1.cc0000644000175000017500000000016412257522663015642 0ustar frankfrank#include "process.ih" Process::Process(std::string const &command) : Process(ALL, NO_PATH, 0, 200, command) {} bobcat-3.19.01/process/driver/0000755000175000017500000000000012257522663015066 5ustar frankfrankbobcat-3.19.01/process/driver/sha1sum.cc0000644000175000017500000000103012257522663016750 0ustar frankfrank#include #include #include "../../processenums/processenums" #include "../../processdata/processdata.decl" #include "../process" using namespace std; using namespace FBB; int main() try { Process sha1sum(Process::CIN | Process::COUT, "/usr/bin/sha1sum"); sha1sum.start(); sha1sum << cin.rdbuf() << eoi; string line; while (getline(sha1sum, line)) cout << line << '\n'; } catch (exception const &err) { cerr << err.what() << endl; return 0; } catch (int x) { return 0; } bobcat-3.19.01/process/driver/pipe.cc0000644000175000017500000000067512257522663016342 0ustar frankfrank#include #include "../../processenums/processenums" #include "../../processdata/processdata.decl" #include "../process" using namespace std; using namespace FBB; int main() { // Nota bene: by default IOMode equals Process::ALL Process p1(Process::CIN, "/bin/cat"); Process p2(Process::STD, "/bin/cat"); Process p3(Process::STD, "/bin/cat"); (p1 | p2 | p3).start(); p3 << cin.rdbuf() << eoi; } bobcat-3.19.01/process/driver/discontinue/0000755000175000017500000000000012222576533017407 5ustar frankfrankbobcat-3.19.01/process/driver/discontinue/build0000755000175000017500000000005212222576533020431 0ustar frankfrank#!/bin/sh g++ -o driver *.cc -lbobcat -s bobcat-3.19.01/process/driver/discontinue/discontinue.cc0000644000175000017500000000077312222576533022251 0ustar frankfrank#include #include #include #include using namespace std; pid_t discontinue(pid_t procId) { if (procId == 0) return 0; int ret; if ((ret = kill(procId, SIGHUP)) && (ret = kill(procId, SIGHUP))) ret = kill(procId, SIGKILL); cout << "Process " << procId << " killed with return value " << ret << endl; if (!ret) wait(0); return 0; } bobcat-3.19.01/process/driver/discontinue/demo.cc0000644000175000017500000000466612222576533020656 0ustar frankfrank#include #include #include #include #include pid_t discontinue(pid_t procId); extern char **environ; using namespace std; using namespace FBB; int main(int argc, char **argv) { if (argc == 1) { cout << "a.out sleep-1 sleep-2\n" "\n"; return 1; } pid_t p1 = fork(); if (p1 < 0) { cout << "Fork 1 failed\n"; return 1; } if (p1 == 0) // child runs the process { // char *name[] = {argv[1], 0}; // cout << "Child 1 starts " << argv[1] << endl; // execve(name[0], name, environ); // cout << "Child 1 failed\n"; // return 1; size_t sleepTime = A2x(argv[1]); cout << "Child 1 sleeps for " << sleepTime << "secs\n"; sleep(sleepTime); cout << "Child 1 wakes up\n"; return 0; // stop after waking up } cout << "Started process 1: " << p1 << endl; // parent process continues pid_t p2 = fork(); // child waits at most arg2 seconds if (p2 < 0) { cout << "Fork 2 failed\n"; p1 = discontinue(p1); return 1; } if (p2 == 0) // child runs the process { size_t sleepTime = A2x(argv[2]); cout << "Child 2 sleeps for " << sleepTime << "secs\n"; sleep(sleepTime); cout << "Child 2 wakes up\n"; return 0; // stop after waking up } cout << "Started sleeper process 2: " << p2 << endl; string cmd; while (p1 || p2) { cout << "Enter a command\n"; getline(cin, cmd); cout << "Command entered: " << cmd << endl; if (p1) { if (waitpid(p1, 0, WNOHANG) > 0) // p1 has changed { cout << "Process 1 (" << p1 << ") has stopped\n"; p1 = 0; p2 = discontinue(p2); } } if (p2) { if (waitpid(p2, 0, WNOHANG) > 0) // p1 has changed { cout << "Process 2 (" << p2 << ") has stopped\n" "Forcefully end process 1 (" << p1 << ")\n"; p2 = 0; p1 = discontinue(p1); } } } cout << "Ending. All child processes should have disappeared\n" "(Press enter to end this program) "; getline(cin, cmd); return 0; } bobcat-3.19.01/process/driver/build0000755000175000017500000000326412257522663016120 0ustar frankfrank#!/bin/sh precompile() { cd .. cd ../signal icmbuild cd ../processdata icmbuild cd ../process icmbuild cd driver } compile() { precompile echo compiling $1.cc $2 g++ --std=c++11 -o $1 $2 $1.cc \ -L../tmp -lprocess \ -L../../processdata/tmp -lprocessdata \ -L../../signal/tmp -lsignal \ -lbobcat -s } case $1 in (pipe|gpg|sha1sum|limit|ls) compile $1 ;; (sort|thread) compile $1 -pthread ;; (all) compile cincoutcerr compile $1 -pthread ;; (clean) rm -f pipe gpg sort sha1sum thread limit ls all cincoutcerr rm -rf ../tmp ../../*/tmp ;; (*) echo " Provide the name of the test as first argument. The executable receives the name of the test. The test-name plus .cc extension is the name of the test program source file. Available tests are: all - stdin is split over stdout and stderr using multi-threading gpg - stdin is a PGP encrypted file, stdout is the decrypted file, stderr shows the result of the signature verification limit - limits process time to 5 seconds, while copying stdin to stdout using /bin/cat ls - show directory contents: no input, only std output pipe - stdin is passed through 3 /bin/cat programs, and is then written to stdout sha1sum - compute the input's sha1sum not using multi-threading sort - multi threading is used when sorting stdin to stdout, where sort's output is extracted from the Process object thread - compute the input's sha1sum using multi-threading clean - not a test, but removes the test binaries " ;; esac bobcat-3.19.01/process/driver/spawn/0000755000175000017500000000000012257522663016216 5ustar frankfrankbobcat-3.19.01/process/driver/spawn/parentprocess.cc0000644000175000017500000000012512257522663021413 0ustar frankfrank#include "spawn.ih" void Spawn::parentProcess() { d_insertPipe.writeOnly(); } bobcat-3.19.01/process/driver/spawn/spawn.h0000644000175000017500000000142612257522663017522 0ustar frankfrank#ifndef INCLUDED_SPAWN_ #define INCLUDED_SPAWN_ #include #include #include #include #include #include #include #include class Spawn: public FBB::Fork, public std::ostream// , public std::istream { FBB::Pipe d_insertPipe; // FBB::Pipe d_extractPipe; // FBB::Pipe d_errPipe; FBB::OFdStreambuf d_insertBuffer; // FBB::IFdStreambuf d_extractBuffer; // FBB::IFdStream d_errStream; std::string d_command; public: Spawn(std::string const &command); void end(); private: void childProcess() override; void parentProcess() override; void childRedirections() override; }; #endif bobcat-3.19.01/process/driver/spawn/main.cc0000644000175000017500000000035312257522663017452 0ustar frankfrank#include "spawn.h" using namespace std; int main(int argc, char **argv) try { Spawn spawn(argv[1]); ifstream in(argv[2]); spawn.fork(); spawn << in.rdbuf(); spawn.end(); } catch (int x) { return 0; } bobcat-3.19.01/process/driver/spawn/childredirections.cc0000644000175000017500000000027312257522663022225 0ustar frankfrank#include "spawn.ih" void Spawn::childRedirections() { d_insertPipe.readFrom(STDIN_FILENO); // d_extractPipe.writtenBy(STDOUT_FILENO); // d_errPipe.writtenBy(STDERR_FILENO); } bobcat-3.19.01/process/driver/spawn/spawn1.cc0000644000175000017500000000057012257522663017740 0ustar frankfrank#include "spawn.ih" // 1: program[0] // 2: command // 3: cin-name // 4: cout-name // 5: cerr-name Spawn::Spawn(std::string const &command) : d_command(command), d_insertBuffer(d_insertPipe.writeFd(), 10000) // d_extractBuffer(d_extractPipe.readOnly()), // d_errStream(d_errPipe.readOnly()) { rdbuf(&d_insertBuffer); // rdbuf(&d_extractBuffer); } bobcat-3.19.01/process/driver/spawn/spawn.ih0000644000175000017500000000030112257522663017662 0ustar frankfrank#include "spawn.h" #include #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/process/driver/spawn/childprocess.cc0000644000175000017500000000054012257522663021206 0ustar frankfrank#include "spawn.ih" void Spawn::childProcess() { vector cmd(String::split(static_cast(0), d_command)); char const **args = String::argv(cmd); execv(args[0], const_cast(args)); throw 0; // this should not be reached, but if so main properly ends. } bobcat-3.19.01/process/driver/spawn/end.cc0000644000175000017500000000016312257522663017273 0ustar frankfrank#include "spawn.ih" void Spawn::end() { flush(); ::close(d_insertPipe.writeFd()); waitForChild(); } bobcat-3.19.01/process/driver/pipes/0000755000175000017500000000000012222576533016203 5ustar frankfrankbobcat-3.19.01/process/driver/pipes/demo.cc0000644000175000017500000000166412222576533017445 0ustar frankfrank#include #include #include #include #include #include #include using namespace FBB; using namespace std; int main () { pid_t pid; Pipe pin; Pipe pout; pin.verify(); pout.verify(); pid = vfork(); if (pid == (pid_t) 0) { pin.readFrom(STDIN_FILENO); pout.writtenBy(STDOUT_FILENO); execl("/usr/bin/sha1sum", "sha1sum", 0); perror("exec prog1"); return 1; } else { close(pout.writeFd()); close(pin.readFd()); OFdStream out(pin.writeFd()); out << "These are the data" << endl; close(pin.writeFd()); IFdStream in(pout.readFd()); string line; while (getline(in, line)) cerr << line << endl; waitpid(pid, NULL, 0); close(pout.readFd()); return 0; } } bobcat-3.19.01/process/driver/all.cc0000644000175000017500000000122112257522663016141 0ustar frankfrank#include #include #include #include "../../processenums/processenums" #include "../../processdata/processdata.decl" #include "../process" using namespace FBB; using namespace std; //CODE void collect(ostream *outStream, streambuf *rdbuf) { *outStream << rdbuf << flush; } int main() { string cmd(getcwd(0, 0)); cmd += "/cincoutcerr"; Process all(Process::ALL, cmd); all.start(); thread outThread(collect, &cout, all.childOutStream().rdbuf()); thread errThread(collect, &cerr, all.childErrStream().rdbuf()); all << cin.rdbuf() << eoi; outThread.join(); errThread.join(); } //= bobcat-3.19.01/process/driver/cincoutcerr.cc0000644000175000017500000000060312257522663017714 0ustar frankfrank#include using namespace std; // Generates output to cout and cerr, and reads cin int main() { string line; size_t count = 0; while (getline(cin, line)) { ++count; if (count % 5 == 0) cerr << "Cerr line " << count << ": " << line << endl; else cout << "Cout line " << count << ": " << line << endl; } } bobcat-3.19.01/process/driver/manual/0000755000175000017500000000000012222576533016340 5ustar frankfrankbobcat-3.19.01/process/driver/manual/redirchild.cc0000644000175000017500000000022712222576533020761 0ustar frankfrank#include "main.ih" void redirectChild() { d_child_inp->readFrom(STDIN_FILENO); // set up the pipes d_child_outp->writtenBy(STDOUT_FILENO); } bobcat-3.19.01/process/driver/manual/main.cc0000644000175000017500000000305112222576533017572 0ustar frankfrank#include "main.ih" int main(int argc, char **argv) try { cout << "Enter for sha1sum\n"; if (getline(cin, line)) { // start.cc newPipes(); // forking.cc if ((pid = fork()) < 0) return 1; if (pid == 0) // child { redirectChild(); childSha1(); } parentRedirections(); parentCloseIn(); finalization(); } cout << "Enter for manual cat\n"; if (getline(cin, line)) { try { while (true) { newPipes(); if ((pid = fork()) < 0) return 1; if (pid == 0) // child { redirectChild(); childEchoes(); return 0; } parentRedirections(); parentCat(); finalization(); } } catch (bool) {} } cout << "Enter for ls-list\n"; if (getline(cin, line)) { newPipes(); if ((pid = fork()) < 0) return 1; if (pid == 0) // child { redirectChild(); childLs(); } parentRedirections(); parentOut(); finalization(); } return 0; } catch (...) { return 1; } bobcat-3.19.01/process/driver/manual/newpipes.cc0000644000175000017500000000035412222576533020503 0ustar frankfrank#include "main.ih" void newPipes() { oldIn = d_child_inp.get() ? d_child_inp->writeFd() : -1; oldOut = d_child_outp.get() ? d_child_outp->readFd() : -1; d_child_inp.reset(newPipe()); d_child_outp.reset(newPipe()); } bobcat-3.19.01/process/driver/manual/parentclosein.cc0000644000175000017500000000023212222576533021512 0ustar frankfrank#include "main.ih" void parentCloseIn() { io << "Hello world" << endl; close(); while (getline(io, line)) cout << line << endl; } bobcat-3.19.01/process/driver/manual/mewpipe.cc0000644000175000017500000000015012222576533020311 0ustar frankfrank#include "main.ih" Pipe *newPipe() { Pipe *ret = new Pipe; ret->verify(); return ret; } bobcat-3.19.01/process/driver/manual/parentcat.cc0000644000175000017500000000073012222576533020630 0ustar frankfrank#include "main.ih" void parentCat() { while (true) { cout << "Empty line stops, q breaks echoing: "; if (!getline(cin, line)) { cout << "End of input: exiting\n"; throw 0; } if (line == "") return; if (line == "q") throw false; io << line << endl; line.erase(); getline(io, line); cout << "received line: " << line << endl; } } bobcat-3.19.01/process/driver/manual/data.cc0000644000175000017500000000070312222576533017560 0ustar frankfrank#include "main.ih" auto_ptr d_child_inp; // cin read by the CHILD auto_ptr d_child_outp; // cout written by the CHILD OFdStreambuf d_childCinbuf; IFdStreambuf d_childCoutbuf; ostream d_childCin(0); // Parent inserts child cin istream d_childCout(0); // Parent extr. child cout IOStream io(d_childCout, d_childCin); pid_t pid; string line; int p1; int p2; int oldIn; int oldOut; bobcat-3.19.01/process/driver/manual/childls.cc0000644000175000017500000000024112222576533020266 0ustar frankfrank#include "main.ih" void childLs() { char *args[] = {const_cast("/bin/ls"), 0}; execv(args[0], args); std::cerr << "CHILD FORK FAILED\n"; } bobcat-3.19.01/process/driver/manual/main.ih0000644000175000017500000000214612222576533017611 0ustar frankfrank#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace FBB; extern std::auto_ptr d_child_inp; // cin read by the CHILD extern std::auto_ptr d_child_outp; // cout written by the CHILD extern OFdStreambuf d_childCinbuf; extern IFdStreambuf d_childCoutbuf; extern ostream d_childCin; // Parent inserts child cin extern istream d_childCout; // Parent extr. child cout extern IOStream io; extern int p1; extern int p2; extern int oldIn; extern int oldOut; extern pid_t pid; extern string line; void close(); Pipe *newPipe(); void newPipes(); void redirectChild(); void childEchoes(); void childLs(); void childSha1(); void parentRedirections(); void parentCat(); void parentOut(); void parentCloseIn(); void finalization(); bobcat-3.19.01/process/driver/manual/parentout.cc0000644000175000017500000000021612222576533020667 0ustar frankfrank#include "main.ih" void parentOut() { size_t count = 0; while (getline(io, line)) cout << ++count<< ": " << line << endl; } bobcat-3.19.01/process/driver/manual/childsha1.cc0000644000175000017500000000025512222576533020511 0ustar frankfrank#include "main.ih" void childSha1() { char *args[] = {const_cast("/usr//bin/sha1sum"), 0}; execv(args[0], args); std::cerr << "CHILD FORK FAILED\n"; } bobcat-3.19.01/process/driver/manual/parentredirs.cc0000644000175000017500000000054112222576533021351 0ustar frankfrank#include "main.ih" void parentRedirections() { d_childCinbuf.open(p1 = d_child_inp->writeOnly()); d_childCin.rdbuf(&d_childCinbuf); d_childCoutbuf.open(p2 = d_child_outp->readOnly()); d_childCout.rdbuf(&d_childCoutbuf); if (oldIn != -1) ::close(oldIn); if (oldOut != -1) ::close(oldOut); io.clear(); } bobcat-3.19.01/process/driver/manual/childechoes.cc0000644000175000017500000000027112222576533021121 0ustar frankfrank#include "main.ih" void childEchoes() { while (getline(cin, line)) { cerr << "Child receives: " << line << endl; cout << "Child saw: " << line << endl; } } bobcat-3.19.01/process/driver/manual/finalization.cc0000644000175000017500000000030712222576533021336 0ustar frankfrank#include "main.ih" void finalization() { cout << "USed pipes " << p1 << ", " << p2 << endl; kill(pid, SIGTERM); cout << "Wait returns " << wait(0) << ", child pid = " << pid << endl; } bobcat-3.19.01/process/driver/manual/close.cc0000644000175000017500000000021312222576533017750 0ustar frankfrank#include "main.ih" void close() { ::close(d_child_inp->writeFd()); d_child_inp.reset(newPipe()); d_child_inp->writeOnly(); } bobcat-3.19.01/process/driver/driver.cc0000644000175000017500000000641212257522663016673 0ustar frankfrank//#ifdef BOBCAT #include //#else // #include "process" //#endif #include #include #include using namespace std; using namespace FBB; void prompt(char const *task) { cout << "Press Enter to start " << task << endl; cin.ignore(INT_MAX, '\n'); } int main(int argc, char **argv) try { cout << "Size of Process: " << sizeof(Process) << endl; string line; // Nota bene: without IOMode you get CIN, COUT and CERR Process p1(Process::CIN, "/bin/cat"); Process p2(Process::STD, "/bin/cat"); Process p3(Process::STD, "/bin/cat"); prompt("sending lines (until empty) to cat | cat | cat"); (p1 | p2 | p3).start(); while (getline(cin, line) && not line.empty()) { cout << "Entering " << line << endl; p3 << line << endl; } p3.close(); p3.waitForChild(); // // Process process(Process::CIN | Process::COUT, // "/usr/bin/sha1sum"); // // prompt("sha1sum"); // process.start(); // process << "Hello world\n"; // input to sha1sum // process.close(); // process >> line; // retrieve the value // cout << line << endl; // process.stop(); // // prompt("cat, ignoring its output"); // process.setCommand("/bin/cat"); // process.setIOMode(Process::CIN | Process::IGNORE_COUT); // // process.start(); // process << "Hello world\n"; // input to sha1sum // process.close(); // // line.clear(); // if (process >> line) // retrieve the value // cout << ">>>" << line << "<<<" << endl; // process.stop(); // // //// if (argc > 1) // sending an e-mail //// { //// cout << "Sending mail to " << argv[1] << endl; //// prompt("/usr/bin/mail"); //// process.setCommand("/usr/bin/mail -s 'from Process' "); //// process += argv[1]; //// process.start(Process::CIN); //// process << "This mail was sent by the process drive\n"; //// process << "It consists of multiple lines of text\n"; //// process.close(); //// process.waitForChild(); //// } // // prompt("5 seconds IO to /bin/cat"); // process.setIOMode(Process::CIN | Process::COUT); // process.setTimeLimit(5); // change time limit // // process = "/bin/cat"; // while (process.active()) // { // cout << "? "; // getline(cin, line); // process << line << endl; // to /bin/cat // line.clear(); // if (!getline(process, line)) // from /bin/cat // break; // cout << "Received: " << line << endl; // } // cout << "/bin/cat forcefully terminated\n"; // // process.setTimeLimit(0); // // cout << "3 times running /bin/ls\n"; // // for (size_t trial = 0; trial < 3; ++trial) // { // prompt("ls"); // // process(Process::COUT) = "/bin/ls"; // // cerr << process.str() << endl; // size_t count = 0; // while (getline(process, line)) // cout << ++count << ": " << line << endl; // } // } catch (exception const &err) { cerr << "CAUGHT EXCEPTION: " << err.what() << endl; return 1; } catch (bool) { return 0; } catch (...) { cerr << "Unrecognized exception in main()\n"; return 0; } bobcat-3.19.01/process/driver/gpg.cc0000644000175000017500000000065412257522663016157 0ustar frankfrank#include "../../processenums/processenums" #include "../../processdata/processdata.decl" #include "../process" #include using namespace std; using namespace FBB; int main() try { Process gpg(Process::CIN, "/usr/bin/gpg --quiet --batch --decrypt"); gpg.start(); gpg << cin.rdbuf() << eoi; } catch (exception const &err) { cerr << err.what() << endl; return 0; } catch (int x) { return 0; } bobcat-3.19.01/process/driver/ls.cc0000644000175000017500000000050312257522663016011 0ustar frankfrank#include #include "../../processenums/processenums" #include "../../processdata/processdata.decl" #include "../process" using namespace std; using namespace FBB; //CODE int main() { Process process(Process::COUT, "/bin/ls -Fla"); process.start(); cout << process.childOutStream().rdbuf(); } //= bobcat-3.19.01/process/driver/limit.cc0000644000175000017500000000134212257522663016513 0ustar frankfrank#include #include "../../processenums/processenums" #include "../../processdata/processdata.decl" #include "../process" using namespace std; using namespace FBB; //CODE int main() { Process process(Process::CIN | Process::COUT, "/bin/cat"); process.setTimeLimit(5); process.start(); while (true) { cout << "? "; string line; if (not getline(cin, line)) return 0; process << line << endl; // to /bin/cat line.clear(); if (not getline(process, line)) // from /bin/cat break; cout << "Received: " << line << endl; } cout << "/bin/cat time limit of 5 seconds reached: child process ended\n"; } //= bobcat-3.19.01/process/driver/thread.cc0000644000175000017500000000101012257522663016634 0ustar frankfrank//#include #include "../process" #include #include using namespace std; using namespace FBB; void collect(streambuf *buf) { cout << buf; } int main() try { Process sha1sum(Process::CIN | Process::COUT, "/usr/bin/sha1sum"); sha1sum.start(); thread out(collect, sha1sum.childOutStream().rdbuf()); sha1sum << cin.rdbuf() << eoi; out.join(); } catch (exception const &err) { cerr << err.what() << endl; return 0; } catch (int x) { return 0; } bobcat-3.19.01/process/driver/sort.cc0000644000175000017500000000106612257522663016367 0ustar frankfrank#include #include #include "../../processenums/processenums" #include "../../processdata/processdata.decl" #include "../process" using namespace std; using namespace FBB; void collect(streambuf *buf) { cout << buf; } int main() try { Process sort(Process::CIN | Process::COUT, "/usr/bin/sort"); sort.start(); thread out(collect, sort.childOutStream().rdbuf()); sort << cin.rdbuf() << eoi; out.join(); } catch (exception const &err) { cerr << err.what() << endl; return 0; } catch (int x) { return 0; } bobcat-3.19.01/process/start2.f0000644000175000017500000000026012257522663015157 0ustar frankfrankinline void Process::start(IOMode mode) { start(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC), d_setProcessType, d_setTimeLimit); } bobcat-3.19.01/process/start3.f0000644000175000017500000000021512257522663015160 0ustar frankfrankinline void Process::start(IOMode mode, ProcessType type) { start(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC), type, d_setTimeLimit); } bobcat-3.19.01/process/discontinue.cc0000644000175000017500000000047612257021317016423 0ustar frankfrank#include "process.ih" pid_t Process::discontinue(RetPid &proc) { if (proc.pid > 0) { kill(proc.pid, SIGHUP) && kill(proc.pid, SIGHUP) && kill(proc.pid, SIGTERM); proc.pid = waitpid(proc.pid, &proc.ret, 0); } return proc.pid = 0; } bobcat-3.19.01/process/timelimit.f0000644000175000017500000000011012256265017015723 0ustar frankfrankinline size_t Process::timeLimit() const { return d_setTimeLimit; } bobcat-3.19.01/process/rmbackticks.cc0000644000175000017500000000044312257522663016400 0ustar frankfrank#include "process.ih" void Process::rmBackticks() { if (d_command.front() == '`' && d_command.back() == '`') // rm backticks { d_command.resize(d_command.length() - 1); // rm last backtick d_command.erase(0, 1); // rm front backtick } } bobcat-3.19.01/process/opfun2.f0000644000175000017500000000032712257522663015155 0ustar frankfrankinline Process &Process::operator()(IOMode mode, ProcessType type) { return operator()(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC), type, d_setTimeLimit); } bobcat-3.19.01/process/childprocess.cc0000644000175000017500000000154612257522663016572 0ustar frankfrank#include "process.ih" void Process::childProcess() { ExecContext ec; if (d_processType != USE_SHELL) ec = analyzeCommand(); // No system, so run execl() or execle() else { ec.argv = new char const *[4]; ec.argv[0] = "/bin/sh"; ec.argv[1] = "-c"; ec.argv[2] = d_command.c_str(); ec.argv[3] = 0; } #ifdef BOBCAT_DIY_CLOEXEC_ if (d_closedByChild != 0) close(d_closedByChild); #endif (*(d_processType == USE_PATH ? execvp : execv)) (ec.argv[0], const_cast(ec.argv)); throw Exception() << "Process: cannot execv[p] " << d_command; } // std::cerr << "ChildOutput starts as:\n"; // for (char const **cp = ec.argv; *cp; ++cp) // std::cerr << " " << *cp << endl; // std::cerr << "======================\n"; bobcat-3.19.01/process/process.ih0000644000175000017500000000110112257522663015564 0ustar frankfrank#include "process" #include #include #include #include #include #include #include #include #include #include #include "../processdata/processdata.decl" using namespace std; using namespace FBB; struct Process::ExecContext { size_t argc; // must eventually be at least 1 char const **argv; // 0-terminated array of pointers to the // arguments }; #include "retpid1.f" bobcat-3.19.01/process/process5.cc0000644000175000017500000000115312260243246015634 0ustar frankfrank#include "process.ih" Process::Process(IOMode mode, ProcessType processType, size_t timeLimit, size_t bufSize, string const &command) : d_active(false), d_timeLimit(timeLimit), d_processType(processType), d_setTimeLimit(timeLimit), d_setProcessType(processType), d_command(command), d_oChildIn(0), // initialize the streams with 0-buffers d_iChildOut(0), d_iChildErr(0), d_data(new ProcessData(bufSize)) { d_setMode = sanitizeIOMode(mode); // connect the input and output streams to Process open(d_iChildOut, d_oChildIn); } bobcat-3.19.01/process/system3.f0000644000175000017500000000016112257522663015347 0ustar frankfrankinline void Process::system(IOMode mode, size_t timeLimit) { start(mode, USE_SHELL, timeLimit, bufSize()); } bobcat-3.19.01/process/opinsert.f0000644000175000017500000000025012256265017015576 0ustar frankfranktemplate Process &Process::operator<<(Type const &value) { if (active()) dynamic_cast(*this) << value; return *this; } bobcat-3.19.01/process/setcommand.f0000644000175000017500000000013112256265017016063 0ustar frankfrankinline void Process::setCommand(std::string const &command) { d_command = command; } bobcat-3.19.01/process/setiomode.f0000644000175000017500000000012612257522663015731 0ustar frankfrankinline void Process::setIOMode(IOMode mode) { d_setMode = sanitizeIOMode(mode); } bobcat-3.19.01/process/start2.cc0000644000175000017500000000146012257522663015322 0ustar frankfrank#include "process.ih" void Process::start(IOMode mode, ProcessType type, size_t timeLimit, size_t bufferSize) { if (d_active) stop(); size_t savedBufSize = bufSize(); setBufSize(bufferSize); d_active = true; d_timeLimit = timeLimit; d_processType = type; rmBackticks(); // rm backticks from d_command sanitizeIOMode(mode); // not yet using the time limit // thread d_data->d_limit = thread(limiter, this); forking(); setBufSize(savedBufSize); d_mode = d_setMode; // revert to the default process d_processType = d_setProcessType; // parameters for a next run d_timeLimit = d_setTimeLimit; } bobcat-3.19.01/process/process3.cc0000644000175000017500000000023112257522663015637 0ustar frankfrank#include "process.ih" Process::Process(size_t mode, ProcessType type, std::string const &command) : Process(iomode(mode), type, 0, 200, command) {} bobcat-3.19.01/process/eoi2.f0000644000175000017500000000007012257522663014575 0ustar frankfrank inline void Process::eoi() { *this << FBB::eoi; } bobcat-3.19.01/process/closewritefd.cc0000644000175000017500000000013612257021317016562 0ustar frankfrank#include "process.ih" void Process::closeWriteFd(Pipe &pipe) { close(pipe.writeFd()); } bobcat-3.19.01/process/escapedstring.x0000644000175000017500000000206312222576533016615 0ustar frankfrank#include "process.ih" // On entry, `begin' points at the beginning of the stand-alone escape // character. // On exit, the character is unescaped and returned, and `begin' points // immediately beyond the characters defining the escape-sequence. int Process::escapedString(ConstIter &begin, ConstIter const &end) { if (begin + 1 == end) // at least one char. should follow throw Exception() << "Process " << d_command << ": trailing \\"; string escaped(begin, end); // local copy of the escaped text // cut the copy at the next backslash escaped = escaped.substr(0, escaped.find('\\', 1)); size_t preLength = escaped.length(); // unescape the escape-sequence escaped = String::unescape(escaped); // reposition begin beyond the chars of // the escape sequence begin += 1 + preLength - escaped.length(); return escaped[0]; // return the escaped character } bobcat-3.19.01/process/cerr.cc0000644000175000017500000000047212257522663015040 0ustar frankfrank#include "process.ih" std::istream &Process::cerr() { static bool called = false; if (not called) { called = true; std::cerr << "WARN: replace Process::cerr() calls by " "Process::childErrStream() calls\n"; } return childErrStream(); } bobcat-3.19.01/process/whichstream.cc0000644000175000017500000000121312257522663016415 0ustar frankfrank#include "process.ih" Process::ChildOutput Process::whichStream() { d_selector.wait(); switch (size_t count = d_selector.nReady()) { case 0: return NOTHING_AVAILABLE; case 1: return d_selector.readFd() == d_iChildOutPipe.readFd() ? CHILD_COUT : CHILD_CERR; case 2: return CHILD_COUT | CHILD_CERR; default: throw Exception() << "Process::whichStream(): internal error. " "d_selector.nReady() returns " << count << " (should be <= 2)"; } } bobcat-3.19.01/process/split.x0000644000175000017500000000241312222576533015114 0ustar frankfrank#include "process.ih" vector Process::split(ConstIter begin, ConstIter const &end) { vector ret; string next; for (; begin != end; ) { switch (*begin) { case '"': // dquoted string: accept all until the // next, and then do unescape. next += dquotedString(begin, end); break; case '\'': // quoted string: accept all until // the next ', without unescaping next += quotedString(begin, end); break; case '\\': // unescape a lone escape sequence next += escapedString(begin, end); break; case ' ': // mere blanks end the current element. case '\t': if (next.length()) { ret.push_back(next); next.clear(); } ++begin; break; default: // add remaining chars to the next element next += *begin++; break; } } if (next.length()) // add any remaining element ret.push_back(next); return ret; } bobcat-3.19.01/process/stop.cc0000644000175000017500000000063312257522663015071 0ustar frankfrank#include "process.ih" int Process::stop() { if (!d_active) return -1; d_oChildIn.flush(); d_oChildInbuf.open(-1); d_iChildOutbuf.open(-1); d_iChildErrbuf.open(-1); closeWriteFd(d_oChildInPipe); closeReadFd(d_iChildOutPipe); closeReadFd(d_iChildErrPipe); discontinue(d_child); d_data->d_limit.join(); d_active = false; return d_child.ret; } bobcat-3.19.01/process/parentredirections.cc0000644000175000017500000000173112257021317017776 0ustar frankfrank#include "process.ih" void Process::parentRedirections() { d_selector = Selector(); if (d_setMode & CLOSE_ON_EXEC) closeChildInputOnExec(); if (d_mode & CIN) { int fd = d_oChildInPipe.writeOnly(); if (not (d_setMode & IN_PIPE)) { d_oChildInbuf.open(fd, 200); d_oChildIn.rdbuf(&d_oChildInbuf); } } if (d_mode & (COUT | MERGE_COUT_CERR)) { int fd = d_iChildOutPipe.readOnly(); if (not (d_setMode & OUT_PIPE)) { d_iChildOutbuf.open(fd, 200); d_iChildOut.rdbuf(&d_iChildOutbuf); d_selector.addReadFd(fd); } } else closeWriteFd(d_iChildOutPipe); if (d_mode & CERR) { int fd = d_iChildErrPipe.readOnly(); d_iChildErrbuf.open(fd, 200); d_iChildErr.rdbuf(&d_iChildErrbuf); d_selector.addReadFd(fd); } clear(); // clears IOStream's streams } bobcat-3.19.01/process/system1.f0000644000175000017500000000013012257522663015341 0ustar frankfrankinline void Process::system() { start(d_mode, USE_SHELL, d_timeLimit, bufSize()); } bobcat-3.19.01/process/operatorassign.cc0000644000175000017500000000031112257522663017135 0ustar frankfrank#include "process.ih" int Process::operator=(std::string const &command) { int ret = stop(); setCommand(command); start(d_mode, d_processType, d_timeLimit, bufSize()); return ret; } bobcat-3.19.01/process/system2.f0000644000175000017500000000014112257522663015344 0ustar frankfrankinline void Process::system(IOMode mode) { start(mode, USE_SHELL, d_timeLimit, bufSize()); } bobcat-3.19.01/process/system4.f0000644000175000017500000000017712257522663015357 0ustar frankfrankinline void Process::system(IOMode mode, size_t timeLimit, size_t bufSize) { start(mode, USE_SHELL, timeLimit, bufSize); } bobcat-3.19.01/process/operatorfun1.cc0000644000175000017500000000025212257522663016526 0ustar frankfrank#include "process.ih" Process &Process::operator()(size_t mode, ProcessType type, size_t timeLimit) { return operator()(iomode(mode), type, timeLimit, bufSize()); } bobcat-3.19.01/process/opfun1.f0000644000175000017500000000016412257522663015153 0ustar frankfrankinline Process &Process::operator()(IOMode mode) { return operator()(mode, d_setProcessType, d_setTimeLimit); } bobcat-3.19.01/process/close2.cc0000644000175000017500000000013612257021317015257 0ustar frankfrank#include "process.ih" void Process::close(int fd) { if (fd != -1) ::close(fd); } bobcat-3.19.01/process/eoi.f0000644000175000017500000000010212257522663014507 0ustar frankfrank inline std::ostream &eoi(std::ostream &str) { return str; } bobcat-3.19.01/process/closechildinputonexec.cc0000644000175000017500000000111112257021317020455 0ustar frankfrank#include "process.ih" void Process::closeChildInputOnExec() { #ifdef BOBCAT_DIY_CLOEXEC_ int writeDup[] = { d_oChildInPipe.readFd(), fcntl(d_oChildInPipe.writeOnly(), F_DUPFD, 4) }; d_closedByChild = writeDup[1]; #else int writeDup[] = { d_oChildInPipe.readFd(), fcntl(d_oChildInPipe.writeOnly(), F_DUPFD_CLOEXEC, 4) }; #endif closeWriteFd(d_oChildInPipe); // OFdStreambuf set at parentRedirections d_oChildInPipe = Pipe(writeDup); } bobcat-3.19.01/process/close.cc0000644000175000017500000000034712257021317015201 0ustar frankfrank#include "process.ih" void Process::close() { d_oChildIn.flush(); closeWriteFd(d_oChildInPipe); if (d_oChildIn.rdbuf() != 0) close(d_oChildInbuf.fd()); d_oChildIn.rdbuf(0); } bobcat-3.19.01/process/childoutstream.f0000644000175000017500000000014212257522663016766 0ustar frankfrankinline std::istream &Process::childOutStream() { return static_cast(*this); } bobcat-3.19.01/process/opextract.f0000644000175000017500000000030012256265017015740 0ustar frankfranktemplate Process &Process::operator>>(Type &value) { if ((available() & CHILD_COUT) || active()) dynamic_cast(*this) >> value; return *this; } bobcat-3.19.01/process-pipe.odp0000644000175000017500000004230112222576524015227 0ustar frankfrankPKîe>>3&¬¨//mimetypeapplication/vnd.oasis.opendocument.presentationPKîe>>Configurations2/statusbar/PKîe>>'Configurations2/accelerator/current.xmlPKPKîe>>Configurations2/floater/PKîe>>Configurations2/popupmenu/PKîe>>Configurations2/progressbar/PKîe>>Configurations2/menubar/PKîe>>Configurations2/toolbar/PKîe>>Configurations2/images/Bitmaps/PKîe>> content.xmlí]ë’ã¸uþŸ§`ÉIjÆQÄ…Ù™ž)g½©JÕl<•WmòÇÅ–¨nz)R!©én—ßÁ?ý~y’ð&€¤HI-©%5ÖÞm‰< €ƒsùøñóÓ"4¾ûIÄÑí™ÖÈð£i< ¢ûÛÑ¿ýûØ}þôãù<˜ú7³xºZøQ6žÆQ h¥7ÅÝÛÑ*‰nb/ Ò›È[øéM6½‰—~Tµº‘©oòß*®¤Ùs¸uóœXnùOÙ¶­ÒÖ»Ûþ—sb¹õ,ñ·m,hA¨róy¼mã§4ÏcúbéeAƒ‹§0ˆ~½=dÙòf2y||4‰'÷äºî$¿[3<­é–«$Ì©fÓ‰úâÇÒ 2Ѥ¢]ø™·-‚Vf)Z-îüdkÑx™×Õeâ§@Ýs»Ém”ùõý~ëÙõý~ƒ˜§^²õ<ˉթBfÛO2“Û.¼ìaÃø:“ŸàfþŸŸ¾¬çU²Øö·­"ªi,·îfA-·ã¸fU4({Î.¶,:)¾KÔ½äIù‰D>í%Ÿzá´–x¼èС PŒýïbÊ׋H"ÝÐOŠÛ5q:Ûøè_~úòóôÁ_xkâ`˜xDiæEkɤ‹ Üz€väõ¢`ë© h[K'“a£ÄíIâ/ã$«h¾ý&¿‚k=d‹p³ w+Òûd6ë$vÈÔ(“ñ÷ÀüÍHÙú'¦Û˜˜¹ªj’Õ‹.ðÃj…×´¥ü§¥Ÿ¢÷^(&ñx‘€ÃÄŽ—7RkuoHOÛ=NLæx6o>±±°§iJ².¹}û¯‰¸7[#(ÿò—$“F)úM–xQ*ž[*åòY0²©™øX°š?´x ì'°tÒ0›8™ÍMø2úTY…öH'õo•ÅâáÓq¾¤Ÿ>ÛBþ_£ø,Dp;š-Ѩ¼0÷`ú?Ã¥bƒ/½{Tµ”/Ž— ?É?5”âΛþzŸÄ«h' r‹ KV0´›Èâ»?ûÓ,í%Ÿé2ôžaߎ3±ν0ÝD“³Wmš=Ï‚Éí³@H xÈn"ɨO`øp«Øyð½ÙÇUï{H”Î÷IIê}þ¸­;Ÿ´fË}â-‚iuyé%¬ͿŒ‹FBϼdV‹¦l"KEH+·)¡¹7~ˆ“à/±X•c/ îa…üy•fÁüyÔ ü.šO×d‹–—_R‰E0†yöâ ú>i õ{»ð’_ýd ývô»Ø5¯ƒ™0X,“LÍ®·e4õ£|‹ßJD;Qi–Ä¿Bƒ(Ž`ØÀf,¯À.Æ0‹cåÿ”šaXÑÖjÒyþϰœBžmœ"ÅòjÜ,Ç¡¸7oAT7°ÄДתñ‚K;È—jùöÉ×t0}±ŒíM2î`)ýôîIƒ¿ì´lØq†µc Kü¯¥>Î\­ð#NûÖD>¿­Å9»­e¡kR¸GŸi³.õæ3Ÿm£Þ^i¾ ëÛÄÌKFò¥±¸r;úc.Ë<ˆü?aëO¿‡KþlIó*’[¶MVÙ&î‘Þïý¹· ³q@ºÕìêÞ*7m‚aÓæd—mík»g^âå ÖìÖWd†á—…ô‹yûßm™ÅíßÍŸ¯þä<†]ôv„é2«ŸQ]ƒçëE›nаLè?•··çµe½îÀ«¸{; ` ¯—ÙúNÅïÆû5Ë%ÅÖLk ¬`ñìdû­5†Ø”­N±>º8oH?a’p‡ÉC³©±Úáž‘+°½HZÓí"9É`¶ÜíæÜ±×Hžh ƒ´l ðüd‚Ðÿî‡åsïVaègFqS\;*¾·Æ"³p;ú¿¿ÿ­î£ôuO'C¨Äõ3ìf??/îâz¾­Rì¬hš?§,‡ºÖþÒ8SûŸò®÷uf‡®â½ºZ´I—ÞêÏãÄ"b~GìV¡wmjë‘ûÕåIˆLBÈÄW)!z@ 9W)!û`Â&½J ±ƒIˆ\¥|øáäs¥zÚ9˜„è•êi÷€ºN=-B'‘}YŠZº]šÓ“âòÆ]<{®¿È‘’Oóh†H2q2¾ßQ3z®£'yb¹Œ:¦™Ÿ”ÙI9²2*9]¥ÀÌ8}ð–~ûAyαŽ)š¯ÕÐ{9Oø¯²"ÏQމmº–-†L\«B-ÔDNuíIŒ›‹«¯Ï¹*¥b»)gØrR²éGX2ßûñÂÏ’ç¼@Hü[,žbXFÌ*ÿ[ñü¼FšyÑ}ÕªµÌI?¢ñ—²¹òcý×2þÇøÏ|Ð[R+9 ƒ¨S€x>!Ø¿MDjé=#!9êðZtô³iÙkáᜂ:ªô&5sÇâ“›C2Ÿ¶‰d.péÊ\Â}âžšKà+\2s-;Á&7]âÈl27:½09å2›„Ed>aQQ[æ(8àsžÀ¯w1J16™ƒ›‹™‘W11‘ÄT½ÈË_Ï¥p?U~Šxgÿ•*rY1¼¦›¬¹êÝ¢.c=àTé–õ3±ãöô =øÃ*Û¥ g jmGê£k×Öº¶ÔµœÈËY&&nCÙ*ZLP¼‚ªuÝ›ŽªÆ@Ϲ¼Á§ãž\©JåÌ› —3…S !ä4®c78uÖWJ•ë§nŒxe+q%–³KðÅ)]E#\-ЬvÇ¡=eð`÷€Sdw ±Ô?–žÓó”n>»7o.µ›¯Ý|íæk7_»ùÚÍ×nþù(ÝKuó™IÖúa“›ÏM1©–ÉqÏ®ÒöÌ¿ÖXºÍ¾ÿÔ aÖÝàðšiæ%Ù»÷7âË?{Ë8ý×Ô˜>á Ü“xê§¢~(Ríä_˜“²M›(£C»*bo÷ÃÒ¦ oM’ì”:kxkˆž|c6(G*£ÜU< è c®Ê©CNnì6HÃeÈ4djÓ†Ó†øÐÆ|øÁÇ&±¹Ê©ƒYC¦¶m«œ:ÌàôØ&ãǶU}ËÉeÙÐÅ ÆZŸt¢¯·ô*‚éa«Š•cuß³qŸ­ì{åßwùFÿ~—~-ãðù ëvm¹nköq—oås«ã6@éÇ™—ùÆ»±eZT¸M-Û±mÇåø½‘Ó…ù}ðläRŠ9L$Ü1´Â6£È†íKüäûQ{³AÌu‰-«ØsDY 7?0JÜÁäuˆ+(-ë…‡>0-e.¤¼½Z+[¢ÜÄmû›(×!›%J`µ¸Ø¡ÆÃ¥ª8± Nå6²‹åñ|à Ël—D&Â6ï”'‡'ŠÝ–5ä‰)ˆl ®´Í K|°- ‚äðѵ1|Èà‹ÃX<¥ fƒr=¶åf›ÔQM›±žøÃ'Ò°;Óv¦¥Á}åWTÜóÒÙÌýñ×?üøË?¼¡$ÖI¦}“LÕ<ÕI¦óô[t’é\’LTf²#Çd+ÁÙWÊ15¢È­S+ˆ¬sL‡pUÀÃr¸“™sdº0]{0íÐÎ1µôƒN2 T'™t’éz“L¶¬L7%™8{²#a£Ñãºî—d'$¸Ê4S•YA¹¤Ø4Y_óëõ,ÐY&eÒY&eÒY&eÒY&eÒY&eÒY&eÚÓþäƒ<˜ÝŽ‚Ùðt‡ •¶;mª ™ÓˆÙ¡ƒX£ÂÜ„.$~6}Èg÷X¨iX(› žU‚\âÀVXŸçÄø<§ð¯ ÿ2ÕâÍ_ìд{ñ,˜~Éš«–5üy Íøþý»#.4¸MƒÛŽÎ¥·1G¢Ám—š…Êñ[DÁ¦Ñʶc)¦1-EyCCp%;)H¬W8—–;´Á)Wò¨UvOf”»'?šVõ¢2Êé~uçÀÅéÓýàñŸl¿ˆ9 F‡³ýÇ׺sÔõìÐKS»HUIà€ÒCŸ\s¬#,Ôd|t›82Q`Û¾bã]ø¾ÏÏRüJŒw‰ø²ËIŠä')¾¶C¡X€¥X€uVûÜ›`}E¥ñW¥ñWˆ¿ÚFijü•hhÁAD¹Üˆ'œ n€‚Q?x¨æ‘pâ?äX!]u¯«îwÌ[êªûƒ$ztÕý[®º?p¡øP¥õŽ…â/÷´4‚[;WÚ¹ÒÎÕ8WÇ?5CÚ Š\?³úå;›ñ"þ1çÃüc,ëj2ç—sW~¦ý¼/ú¹-~>OÇW£Ÿ÷A?k¼î°ƒ¦ñºo[=h¼®Æëj¼îÉÕî¥âu™ÉÜŽˆYóÅæÜ s{‚~{ᙆڞëþ¤¡¶j«¡¶µEi¨­†Úž ÔVCBû¸?$Tƒ}N{¾÷q3ç•qMË9XÖù²ÞvÉ;vwHpý !‘Q`UíXPh(ztê‚€tôéû3´ÏZ!dòÞ÷œ'´Æ"¶2ØéƒZs‚—€ %ìd:ò\¹¡6bŠò/ÉRBÏ©&*0˜œ<9|`Š^©I°#tGÒÙ¸ °_;AN£ª’ ¬/¿s†ŠN8Óê""ýÕÿçêŠ2‹«CpŸ{æçîcy±V½f°*Ö{ø¢ùJ£Üe.A˜Šh™!RT˜rL°KÜ<3ÝåŒbÇr F‰ÕòE‚ö¶1|´à9éÄ1£àRøD8}ÍbOÔ“ÐrÜ,ÇÁbO¢{ŠH¬¢ªÚ“m*ö±;¸!Ţؓ`JQìI°í¢Ø“P&ê>±Má®[<¾X[ƒr=FĘª…3°ÒT¸·ØVšÒô1ãF|ŒcÊšAãF€SØØÖÉ£ÆÈ-Ld^]“[Í-)›5XÕl_¸ÿ‹ÆŸ4k(R&t†‘f±øÓÆ÷‹ï¨H쪀§{‹øŠÊ—­rÛ>Tü‚™‘my/´d·˜Ú1Qó¢þ¾e–`3ʃÅQúÇ­Æ Úß¶×°y ›o´Ó°y ›ßäïšßƯá]¦­¸5Ži+¶µìÖò½¡y0ÃßMÃ8õÓ£a9õ‚Áç¤e«+»E±1 „‘ v°Ã*Nô9~5räÄ1]Ôþ{SÕ ¶®fØ·š¡ÚËt5Õu5ÃQ“bºšáüsJºšaó²ÓÐ{ ½ß9o~1Ð{dËçûlÂJ9òá‘9Vªyºö^”}•èû2i€œ‚\Pâ¨ìd}=ίד@£óÏNßjt¾FçktþEíbv€Îßc¢ht~÷¯ÑùgeÐèüž ƒFç7Ê Ñù¯Ñù¯Ñùç§è4:ÿ,Q\挕^30Üû_!4ŒÎ‡;®C¸íä  TªÅ˜mY„*Ü‚Np>¸‘#VóB”~@àÉbÛ…ÈÅ9­Àä;iŽ8u;^C ±ùžÆækl~Å«Æækl¾Ææ«ƒ¥±ù›¯±ù›¯±ù]Z°[Ëklþ„|^×fê{’ÄQÀMô\ë„]dü„]`·nlq“Ó¡ÀÔ¡^y:\+°åky¸hɬmÄh#F1Çéétã6Qçm^Í•Z$¸O±ÖŒZ3jͨ5ã©5ãÉ^ÝLÇZêë/€«ÙØÊ`¬8SÞM•Ë÷A—R˜­Éíâ¹ÅK¢™e ??&Ü@6ÇxQôË+‰wAô¾©Bb¦ ‰÷-$森áÖ…ÄÞ™;t!ñ>…ÄÇm9.HƒOõ­å"µþúÕŒºàùüazo àù€Xd]ð|T(².x>黯øpõ ‚þRË`ÕÔÎî½ìmc‰~ÛØ«S]Ϭë™Nu=³®gÖõÌr§u=s¿Ðt=s›ûó©gv /±äãÖ3¿“ šß¿Ô|¼öÊæãÇD¯¥²Y—áê2Ü®>\|.3¯,¾wÈ2\D:T†ë”±´×.ÃuM{  (ί —=vñe¸ŽÉ®  —A³‹.ÃmaÙˆIŠPø¾”XïÔµ™í"AQUá"î:¢Ä–‚wµ¡ —ZÈ „9-ª*ÂEvU„ ¤üŒkP¸Fm6\-z,ÂÞñž±¾Qˆ5¸äÊ §4Ÿo,[¼b ¸bÂé A Pì†Ë \D8Î+p‘¸AƒryÞN|¶pRæjnÁ±ª¹eõIü§j6kna\knA}Öܳ$q+4?ðMpÃÊ¡ÈáþVŽÆ¬jÌj£Æ¬jÌêÉü”ö "Q>pA]¥ýÚg(è†3„ÉpvgˆSŒ®çqzÔUŸB¡¥!Ð{¾Þóõžÿv!Ô`·žƒçˆ*ˆ =ˆàµzÏÆä„´@îëüAQ±ð•+}/rn)Ø+  '/ ¾ø)b•cT¶Ó<Ìq÷Q½%Ö¨ÄÕÇ­•«æ9€Æym,s޹VOý²ûûç™æp”µ“€¹'3(ÆÔShp/„æYŽ+UewƒÝJtXÕ€ÏmÇèEˆÞr-æ ÇO¶ÎÉdu@•cð×E–‰Ä7¡þo.’ÝçdÂmÃeM˜æÌÍÄdn¤§Ôf1zXÏÔ@Q[\v *žQ-¶Ui«šþ/ÙíK콩ÚV®k[j[Õ~ûYD÷©ú£‹x•úãïAÜ…ÂòÂ4—Þ$žÏƒ©#¯¯Þųçõ·Y<]-€h<£ þ~úPKo~eM!vMPKîe>> styles.xmlí]Kã6¾ï¯0$7½ýRgz‚ì ,0=2“½´DÛš‘DA’ÛÝ9í?ØÃöÿí/ÙâC2e=,¹Õ¶Ç­ ´É¢Tõ©X,V•¨w?=þèljGÂû±¡êãâzáú~üûç¿+‹ñOïÿòެVžƒï\âl¦J’>û8Áà0¹ã÷ãmÞ”xÉ]ˆœÜ¥Î‰p˜ º“©ïØ­x »XÛáŒXâ§´í`J[‹–íï̈åÑnŒvmSZÀT¾"m?%¾²"ŠC‚¥ÞO¾~½oÒ4ºÓ´Ýn§î,•ÄkͰm[c½9ÃNNmcŸQ¹Ž†}Lo–h†jhm€SÔ–?J+³nƒ%Ž[CƒRTzªQŒ q©^¶»<¦ _ëÖÚõ¸®ÙÙ ¸µž1⢪Xn{U±\yl€ÒMÍó]hÐÉþ÷ða¯WqÐö^”¶•{Qk19µ<ž’³JðÉÎØ5u}¢ñßõ®‘|{)Ž%r§‘ÜA¾“#N‚*ЀÎЀBÁTås¹Ïo-5ÐÖ( ½ÖÐSÚ’ªÆüZ §ZŒ#§9 «öFîbæ&c“~½É ½é:vÝJR`ÇÒÀ|ÀäU=¼ûn\X šÁ>PfZ aDùtL+­âëóoíS¨©c&Vi…˜PwiŒÂ„Nadĵ¹Deˆ*” vQ~°¦¶8Õˆ»2cw¥ÂñûlqäkâûwÔÔä¿âxÄþ¦æ~üs“ÝxæŽâõWòt?ÖGúÈÔG–ÎÛÁD´)mÛ˜úŸcM\/Icò+.J6òE÷AŠ•â?Lý_ »cÞïzIä£gå€nT +oŒ4FÒĘ䟊Ã5µAºªO 'úÌ"©YGê%) ©µƒ\Üæ»x…¶¾ð(F¼m…`Š=ß×1Š6ž3Îh##Ö¦D1<›8õÀá]ôq+h›’$Bô>ž‹ 'E~´AcAmC'ݲ®ì û~œxADÕŠ÷Ãj‰•eŒ¬¨¹Gqá=ÔÁ®Ä…Ëû±’.³®È ]LçõŽØU(#Ì‹Z!?Á¹  Å +‰@@«+'§r•¤Ý&XwÂ%;…ÝÜ!>õ6· ÉŠpŽ2@I~üèËm2ú(}$öèo/Á‡(kbƒR("/uàñ>¢ØãÓ1»[âý ¸˜“(em> ×[´†&²‡lÃ4v~ÿTuK˜o(ÌxýAÿÜŽ>Áü<Êd62yNR”yÍú÷K”錀³.Ô@pŸõý¹Éz„YÇß>V±F?$N>¶V œ¢^¤œ¤R¨¼w㊕wýããx¯ …9ši¦2ÅoY­%×!¾çr‹(ÌÞÎs™Q¡EjjÿÎþ [Ã-/ð .X>Pµr[Tèw`ºRO•ÏÑÌå†á´·jðÊóý\‚¼%çÔ¶gµb"B.Ýe)` è sJï!u,IšR'¦ªÏÇ«”ö”:bo½‘z8®ä2GËs]:¥FÖ®§ÊSQÈbçseg&ÒB§ÿÁÃe›+,½Ò 2™>˜Ï‰•åÖ÷q:â´-,ì'ïR¨O}?þßÿë‘t‘½*iu–óÐ,~øô,‰?îbU¹›L¿gó£I˜¢š'‰ÊǰOYbðdØú:£Šõ^¨øh cr=žÉKï·„ÕBàÄÝ$B“ZÜ$BÓÞ2ÕÉM"4ë !ë&ñ™÷‡ÏÚéEoMnÔNÛ="t›vÚÐ{ƒhúmj©[ìµ´º-ScLî û”5˜oÄ.A4f›„b+߈Ûò=ˆhf‘ æã ]ÿžµ2ä<ûव˜¶ÀMH¶)½a¾Ã’º#é&&ÛõFa¬„ÇÂtþ:‘c!"¼-ã(¿Ç(Û‰qN%q¶^ÌÃFU²ìâÙõÄ,À)ì?ØŽ†,Ð$ãw]±ŽÜÉÔ^ô¥’n ¸ºHKˆy½5$L/pmW0YgØðû^U(y¬Ò¥*1ñö“P ú öåì¤;/ãÌÛ•1Ÿ,îŠâÝCF' ÉMÄkÂ)lУ—xL¥_%t‚ä`íi¬ìEçÁ96ZóG'Ì”›ÏÑq¹$îó%9mö¢Ä*9+ÙYª/ÛT×–Ï']·ÅÓO¾·†ÕŠrë­ž»‹É=¨ë²ƒKYô3?»%^*­´WªÈ“I'E¦"—©6¡s;ÝqM0›Ö„RgyMh?‹ø*Ûöq˜Ý‡ù:£Ê=Ñ÷¹˜Â3X­Ƕ¯ë´™äü.‡;GÕ¨Ù;æÏ·Ûö±øÐ­N‹É#—:½—·,G hNÌ:8M£=FÝ&F†ÑELÕå@*îݳÍö’ønwè^ɬ\-t“а‡—Â$w^Šh€Q²Ï1_åE²ë&Ñ<Ü$Â&°r\ash„ÂM6`µ·¡—ŠfÛav™è¿ˆŠŽ%r¾®c² K¾µ\LûZ.o­ c½@¾£L^&Ð9J&΂KHRüB,úÜ5ð´W»}ƒr$@Ï[o1˜lêC0¹¾PO¿ù`rˆ7LÎŒ•˜£%÷³G{Åh¥°ËÅ.Of‹øRð’Ä\L6±~¥¿¡ùH™[IŽW/w«®k¬¾°¯,éy*9CÞ$BÕUrÿúÏ)Nµ‹³!4¿Ö*¹[­O©®’;E‡®¦ø¢gê¯Jnv£U`ýÕÉÍo´Æ©¿:9û&ñé¯JÎÐoÔP÷X&g×bª/U'×XüƼÅ7†°Ì! Q†ààÜt¢FÄ·†(¥r aˆúüCE 4éô+Õ"Êá³ÊÎ}èiqJAˆjõƒ˜ÙbVÇ4i-b•ÅwlOElÒbV?ˆ™+…(C´åðæ©ˆMûAlÒb]Rñ—BlÖbÓ·ƒØ¼Äfo±E?ˆÍßbv?ˆ-ÞbÉvYYÚ{Zˆ ˆ#呎tŸU«žëú¸eö'gw8ì`8ì`8ì`8ìàzÒ8ÃaÃaçOâ ‡¼ÕdòpØÁpØÁuvÀÉ;(-Ðéž!Ý3¤{®;Ýó-ņÀÂX C`a,\/BC`a, …!°0¾ùÀBE´à &U/ùN0)U‡Ý\` FÄ È;}%¢ÈðÑ3LÏÂþûçúg“Öó>2ù`&7Ä:ø÷ã K°¥à=®ïhýƒªOçÙY…Ït“0ŸXÙoaP ]Nó ³÷S]5-QÑø2 0ç†ya&OnÏÓ¥€¸‡@O ãÒ@œÆ„Ö<Ÿ€ààKYâ'}›~„ËQ²ŽlQ®ž‹¿>è㠚ʞŠÍmÒì~ÓP§¶ÜžbÎU›yL Ø {ûÒ¯¸ÅÈ“k¡ HÀ¸•Ò¢û |‰ƒ"Ü,{9úàF¥ƒÄg5™šåÈ¥PíþœáÜ,IìÒ$ÐÉgo_¥7:ñU˜£ÙwÛèyRûSf+IV„¤GHØ­²Ïq O³’ÐE)øœ;¯Ó93ëør§…Už©Gÿ;æª7èv~’¹jÙó‚;.õåú:&um¦OûWÇ&*kDÇÚÖòaN×¢'“‰Ý‹—¾Et½Xt׋—¾tn,.=“~-O¤,P1>p‘Ïç«ÙºVwî´ïôbÓïeM/1Û&΂C·Ûéƒç‘®¬»'I×í\Û3 ø¹¤k”µ‹©YS2üáÃNVº¦ˆæRàC üjRàC |H)ðË"4¤À‡xûx³?mþôàOþôàOþôU"4øÓƒ?=øÓƒ?=øÓ×âOkµÅ+¢#@IÊ>Ä[Y¦ÈGÏ´‰^qÿ›'‘¸'Îk (CÕýÒ÷zZÐdI²ZRpˆ‰ß@!>ÂD+ê•v(\T)\èb‰A]=R¨¬Ë“‡ý´Ú'Ëå=çAVt!˜^ÅÐTAÂ*ò<^!¡È2k{Qª@“kŸlÕšÙ‡¥O47ËŸD…Œ( bPp|”$ü3a8Î8g|-É“˜ƒ‘˜)ŒŠ^˜@aÁgã°*‘ß#Wj:.û;ÊžàþÎÚ×àiöާaª¦ÙÓ¼v¥ ¬fgXóÛ¼²æ¥4Õœ©S^ýY-/1z]uå÷83¨¯¯®ÍÀJ…Y½k-¾¿ÁûüôGþçëôÇ [‰àTèÙ5Ò \$Džß QSTHJˆÎT{.*ƒ©N¬ýGT UmF¾xCW' Qôzæ;/Ô©eœíÎM+Ãeî~fØK·—°×ªÜžÌžå®êþ&WǨvuŒ¢«S0(2éÁ‰í1§ªa—Lœ¥Nõ‚‰S'ºº°æuöMpPW—.|ñ˧՛÷£"ï?öR© K]ÔK=QmcR'µ`âró*Ë^|X¨L«„‚:™,jQ0lÕ`s¡?‡¬»ãЛCv"ÈVêb^z{âd[Îg­aîîœYrÎN¸““ÖJ‹M]ÕçÓÖó^ZA(ö)ØÆ}võºÚÿr&Öž-J Ö÷¹lyÁ@Ãlt¨sÇ åš!¾Ûï¹jÎß&L[SÖ2Õ˜Ú²’YÙ°*ÎgY2.¶Í¼€È‰¸‘^¶†ÉEÀ%/\‚µòœï¥â>£p8Èš]âlƒüŘäýÿPK5ÝŒ»­PKîe>>“ÇAìiimeta.xml 2011-01-30T12:28:36PT00H25M45S32011-01-30T13:47:29OpenOffice.org/3.2$Linux OpenOffice.org_project/320m19$Build-9505PKîe>>Thumbnails/thumbnail.pngÅWgPÓß¶ý%D‘&E:‚‚H‹Ò”¤ƒH ]©&R‚ Í@°Ð4 ^¤'H¤*Ò"Ò‚H/þ ‘*ýæÎ¼¹ï~¸ÿ7ó>½/gö™sö>kÖÌÞk8ó[l̰̂êZˆ­gÀôÕ=Qì‚FºÚÖ!9k¯˜Ì¹m;c@\ê#?ePqÚI½lÙe,qŸ!¬ö(∓,)¶ªÕ0©.Vͱiâv5ÆÖZÞÙÂXåTÜäk¼}±Ãç$ž4Û!1ŽGsxŒ™9o|]μw:C¤äàà$>‹mþµÛ2ºµ`ëââÂA#*œÀþÜÀŽ /®làM€Sâ*Oƒ‘u®ÖÎÎÒ–罕ýC9O ^Ú}KrÄ‘ç—Üæ»ÌûØÍ>,ëñêh¾ÇbYò§¡tgÆ_¹;y Ѩu\Ö‰º$&–ƒTȪÅüпFˆˆ¸sçŽÃ»û™Ê>Y+h_Ôv1ÛýQÒ«•Í•¨™õèFŠ4B[»m{eò½Ÿ–'%£Ð 1W+²Å­3ª»¡â73^ã5Y{¯æÁRÿááa_¶JLt4év~Ðý²¶–Àe.ä”ssÒÆfdx8hm"hº!èªô¥K:%ÖÆ™jJ(˜_3ÍŠžÛ7§È‘Zø–“ãƒN6õƒÕšdI3^0+¿<®gÀûáÎDÛÅ˶¾„€¶éÆàÞ 2ö`Ç4[ùÙÓ§]ÛÉ&ÖDùp£ƒÏ¥¨:Θò[ìȲMÊ‚´÷/Ä]/e§±ÿ³@ ô(@ Zw¿1¿„%x)P›žxAK„›ÛÚÒò†R;ªÎ‰4}um8¢¿¶¶¶ÿÕu+üë°ÌÜ܈¿ŒŒÅAÖ5ÍûÔò»ïºº ¯ETUUùL¾ãIŽþÜ£'_û‰‚¢"Rž’nÌuîœNrŽÚPc°ŸqÑ÷¡R³çJe(rͪ÷‚……q*Õèøò­„Në‚Â`f–ÃN‘ð6Rú………„C†©Ñ›“ë³ÚY1ÄëLùSέi«l S­.Z[ؼP,¬õ½ït> ]é–Ì T•¬ÓøCpW?^]S¾³úg}.x&´´©iê³Q1%)á½£YÌYá2¯VöÛu(Õꦥ/õ@ÜúäŠV—á§²>ÏX‘a Z‚äÜ„…¡ñ"£äŸot2U½úsâããßÏ„™” ¬§H[•í E˜“B?>eú&-V7ÿãÒ£–(£î7£…R¤[ó9ÚaMëùíZ}àç8 ÷€¹°Zý ¯öPRRº€ÝJjW[3›X…ÒzÓ*)·d ÐBš*¢ó¯2c^Q4¸ú“ûcª,²Â+€á*öÁÕ×—„Ú<'ä_﹦à}sxFHpå7ÿ"w~¨¹WàêXÕ.mº0öïÜÜÜÝóð€¿ ‘É«FÎ{ #=“8€Œ@nÒÛ'lIìƒ ó*j£—;Àƒß‚é]Zÿ¦åË0µÎ{m…DàCæ/ZЧuK£™À‡Ožâ8f5½ÿŒƒA¬Vl˜€»±„§€>áè1[gsC™t¢‚çÑ)D黫ùàV%›vö-(8Ci¶`‡!Î68ª_DúÚN¢0yMØÞ¯oÚW xrøB/Eeï¹iãå˾ƌÊW†ùîäψzåžv–medI>y÷C·”¤áûÈÉùd“E= ¿'x¼)©Y3^ÝÀ#,76Uó w¡¥1©É;Í×ãRlo+›è¤íì§&8ÑÈf%—}ÈÝ(­A•kž[[¡ÜŒbŒ‘.NòõùÕ*rrLÁrl!ª‹·r—Ûsj Wh#ÑšŽÜ­_ÙnÞ>`rùžwÖe¯[G›Ý -Óµíœ6Á¸/Dñ–é#Ü_Ëx´=>ÅÂG<—JÉÓú¾Í]¢p>К‘×òýz…2õóµÛ²Y‚ò¢©«¯"xîÚÆFçõµÅŒ+¢Ñ¾ïïívhVã/AEˆårZÜÜWôùL_œ ŸÏœ]zbpYƖ窽S¶ûµ„éâ]Zé¤íˆµYy¶ÇØo$š|ù¼4Åáv€â%z‡ðص<5!UüçÉ*O‡í½|ÿ#õýŠ+Z¦Dî%Yôô­èA8àï#O¶7ý†6pè½ —ÃgëÏž,0U9Fáêf”Œ"'µ{[B<Éù«Î=3ÜIò uÓГ‰á~™wëö¯Ùg ø·azAÍÐaÿF•OÈÖ:Õ¸;™‚ðÙ†¤¡M¦½é—­·œ>•y[1xò.ÈYÐÊ?D®æÕíæÜ?+ÑÜbsËò!,ÕÀf‡ %1&™ÅŠ=a)ö神µ§ˆ<˜îèëyžºdv¼ô}Ô;ä#Ôï¹ò39C&;Õùõ Ÿ™ðònx'¬óô>ó@ ¢ñí¢Ðekv{ËøÆ`TÆâá¼l¼g±ûñ­±Vp#Ð/×.DZ"¼&@é©QHˆãóq7RãúïªÏ¦Yu^ÛЫWEÝêªM«¤²xP˜‰‡lá´³mr›©.œ±¢¬Þ³ßßMÇ’)i…Ä!ÅñG9jMo S–ž—F¥[c£àJòâ]ø¢Ÿ \Š6²;¼!>&Z»®ñ­0ÑÀØÝð…(îH‰åàôëÇWýýNª—Ž+`ú;.ÀÀ^;×FMRvÙ{‡&Ï…°"ÕRÁÝí §#ßëìjÎÊÇ$˜ÄñŸ‡Iw¹lnýÉì÷¶Xh7òý`–0ê Š›|e .s~/š“¢bq°¿·ä)ÑrÜ$‘ˆ]F Øý/°$ñ·xª’œFçü¡§*2þÍ[_B}Ø å ÊøÎòËúíäË÷–½Ùeì´Û’^;¿«â©èòF•ûލm•tûò±°üF€ûÁ½å}ðãTév†ëAUìõiÑB¼æ>dO®Ö'Nã|*º0l:º)Õ~FwZù¢|èà;r…Ç7ÄÞFÉ©¡WÈñÁ´ïG"}C×ﺖ§M÷ý”:¦Î¾jT¢×ÜÌ»`·ÿÛÙZLp×CÄ|‡\¦VRO±¬™o×qâ¨ABý¹Hež;Šsqr/kphÌ–z‘Âì×_Â|·Ñ¬Olø·5¿oAc°í‰èîs`U–z^= >ÞÈŸß_¶äù Ä^Ht€]Nj¨Sp, Ü•µ:ß‚C‡ùÝ‘aæÍ¿HF˜ba/ç Þ<¬qD*Ô¥háMZo¯Üà퀲~›c–-?Éwè»ïNFœr ÂUíÅ}Xç_à3”×QZŸ7“kõŽ> —¿uJ-›´Ôé9¯CXX &_¿¡£ã£Ñ}Ö)FF[këOŸ©uît ³¼¼ zÓa¥©ª”Øó•ö´ID)‚ÁuG-(°%9VIMDX §Z°uªÃnp¤œ­­9˜6ÅY¨àô!7??¿±Kî0ftj!cµ÷¬ìíí}|dñrÎNH7‰u `)¯õ6ÆÖÉw>½]]±/^¨ÓKŒT8XÄù(ÝÝ™šØ}ºC˜Áî:-0§®h>ª§ ù0еþI¿sC áf:gë8ëïß䩞’7)œ p8ü_@'û´#r@ÿÑïþSeA¬˜'€Üüã´Cˆ÷çÍúÜOîfW€/Oä8þuÝô¢iܱ´˜ uä¹N½ðøFAKóN]_Ú°†êªÛb.–ñp}ÿ—Þdì až¤÷ŸÇzüðÒû`¢o–g€¹à¸;Œœ~Üîø…0øË’ ™9'6qRÞ¡e¥lú¼·¿×«’ž§Î½åï¾ÇSË·'îéÓçs¢¼F›ïè)Ýżÿ.=º|äÏ6·–|éz܆Ï")ïô¿Ê4ð3˜ð—Š‚L¯Y²LGhï*KþÇ×> settings.xmlÝZ[sê6~ï¯ÈxúÐ>BÈ &pHh˜ÃIh §=}öjd­G’C误d å€u:ÍCBléûV»ë½áëO¯!;z!)ò†W9>ñŽ€ûP>mxO£néÊûÔüá'êC=@?«’¥ôy¤·sY_Þnx±àu$’Ê:'!Ⱥòë_m«o®®'dË+¯Œòç†7S*ª—Ëóùüx^=F1-WjµZ9¹»Z ЍDàý7÷lÒúÈ'tº/Êrõæ~D\ m6,–~zrrV^þ¿Z-CÊöå2kK>†‘–y̾Óá4ÜƬÝ9õRª·e¯­eOµá"§^så+7h^§ÊYþ)Q¡ñ‘£ô²‘±áiÊú …ùÚ{¼¬}ßïùJ¥Q@Kaä­nªE¤oR®¼f©Z½¼.ïâ|»• ~~~uRý7¨Y|µvV;/ t:Ëÿ´rY;Ý¿’¨Dy¯lsÁ<ÛXÉíob±Ä0ï[bJ%´'xMã;Mü"hГ©>¶àLj ÷šÂ$Áï äÛ:>zO9‰FhXÂȾ1¥\æ±($1¿û”C.Åò0þ|Õú¢s–ê§ÈÍa,–w„ d‹ÍÉ¡ÿßÕn™õ³Æœ˜ç–Ñr¢`€l‘è­¯/¨–áËŠL•ó˸ړ»\.N”¤O:õmã gm-„XxÍòÞ?W ;Y:H*ò_‘¦þ3ï‹R~ê[Jg€± ÞcîŠX<Þ=Æ „Ë”c¢õgŠ·“å …~v,œ!0Ó 0àÙÀ– ¸'_ø‚›ðÕ¦Ó4TºH]7k#võŸGðªn𛿋Ð$áSxÄe+â@YCF8϶ñ™e|×j1*m "¶=3‰é–~¹‚¾GµcáCàßÁ8³>¶tøÿSrá¸)©Ú—â$BB®ô•ÓKKÝüž/{1ô®®s¿¨Zv‚+ä|© A›‚8ú÷û8A ‡7À1)î²Y ´ˆkŽoÿÂ9¾¹9GO&µ¡¹å¦tÑ2tuûˆáÏ(>öH¯7'y·ÓaFö jÿ±ÕòB,’¼ý‘ùU+ŠØâI‚¸!о®hS¥:2®ðôØÏ™­üøS¬ø9%(Ë4…KÛ±ê2F]JІf¶j&ƒ#MyÐr5)Þ­OæÛ‘Þ9³æ ,9aBb¦4íPeWÉ:ùS¼.Š1 àkóŸéõu=gô©®€ÛÚ>6ü9¨OCËê„Jv†x)êÍj¦”›ù–5Â-ÞÜ_4νŸ£H@5˜µ‹Oí4Ÿ–àòý ¹"ìð¡ðŽ(ßþÙÙ&äÏ xKj¿ÄÜW±«Æ®'“Pñ™›9ô&A›øÏ.ºàMŽ7'ê…It¾u3X¢ 27åJú.UoUJÅÝ’ I5æN¦6 GÖÄà€GxˆÛÖ$0Ú¹wõEFÂ0¢ Ü:Òˆ:‘ߤI-­ã¹--’àH€œmW‡šëêîs Bc!ÉlÖ-t]ÓM‰fÃ8 ]e¡Äâ¿Æ„Qµ­ž"“ºDO—1æ] ôÉb7:­¬Îp^Ò]²Ø³eÆÓ·5—b AÅÛeûG¿’øº|ÅâwJÏÔz8œüÓvÍrô÷:ã꜎ ŒØÙ÷cm~Ò¦—wÞ7)网ÔüPKu߈RÓ$PKîe>>META-INF/manifest.xmlµ•KjÃ0@÷9…ÑÞR›U1q-ôéyìôC3 Éí+’¸m(M±V–Äø½ñX#­6GkªDÔÞµì™?± œòvCË>¶ïõ Û¬++ ªüžÃë´e)ºÆKÔØ8iRà:¯’GÍ×øf4­Õ ÜkuŒ§ê&ƒNËšNZ&C0ZIÊyŠƒëøÙŧ "`~žcØ2ùºåd¹OÆÔAÒ¾e‚‰‡r¹Oyó®×CŠg?.æLîd,ƒ—J<õQ¨ãX\äâ®"‚ÞxIP|H!ïTýw^¹?=¦^ NÞ›bpmå(^5Y°¨ãAö÷ã“»‡'ÍÕTð·”IŒ½zžýô¿fþ‹t2€³c-œíàÙî“Ý9© º ypÃÜðy Dù¾¼–v%~\—ëOPK’È DHiPKîe>>3&¬¨//mimetypePKîe>>UConfigurations2/statusbar/PKîe>>'Configurations2/accelerator/current.xmlPKîe>>äConfigurations2/floater/PKîe>>Configurations2/popupmenu/PKîe>>RConfigurations2/progressbar/PKîe>>ŒConfigurations2/menubar/PKîe>>ÂConfigurations2/toolbar/PKîe>>øConfigurations2/images/Bitmaps/PKîe>>o~eM!vM 5content.xmlPKîe>>5ÝŒ»­ styles.xmlPKîe>>“ÇAìiiÍ&meta.xmlPKîe>>eP¨8S\+Thumbnails/thumbnail.pngPKîe>>u߈RÓ$ Ú9settings.xmlPKîe>>’È DHi2?META-INF/manifest.xmlPKî½@bobcat-3.19.01/process-pipe.pdf0000644000175000017500000100750712222576531015226 0ustar frankfrank%PDF-1.4 %äüöß 2 0 obj <> stream xœµUMO1½ï¯ð‰Ô¿¤hH%n”H=T½µ´BP©\øû}o¼i6»”ö0c?¿ùð<Ço‚{~9ï.ý&ºÒ⦺Ôì§oîÓ…û9ÇÏÓ÷ÁsÃ=³\·qVàø“Ñw wFÎކ؀·?‡¯îÝÔêw[ñãá~¸: 7+|Ú¤×øMjøq©[¢Á7˜±D$ó8HFÝypæh  {pÉ뛀gS!=­,Ãgü^#Üý›D»EY^sš vÀ*ìjgo‡?©8Âf ÄEà!:¼Œ=żrYˆ ˆ&äã*pÚpö,T( lD)É59=NÑÈçÈe¨P> stream xœµWËn[G Ý߯¸ëRg8ä<A€kزK- ‹¢»6-»@³Éï÷Îut’•cDjø’û8~þø û4––öu´f8ýküíÃøïGþ|ý{¼_2??ý Y·~ûÏðùƒ+ç4ü|R¿œþz„jOŸާ/ÃÃiø´á·½½-öÖðo pÝ¡á˜J‚3/ƒdÄØ‰çÑ mêžÇçuEMŒ S Ý­_q¿áÿG˜ûò.ÖžVÕFÍ7Ð+ÎÕeŸ†ï©áEs&£‰" `TÆâ;P3Î×€öbËãú7B˜U }b…¤6hsãWĘù)ÖäbJÔÜRpÎ’;0ç¼íN,‘k =ÇQ)#²{Ã!sÆäb Ds“¤Ò¨!C³óÊ·~l‰Œ;5ñgˆ¥zýFbö‰5¿(yäëÖÒß”à.ûëÎ9/BÄùÔ ½ä Pò¿ò£¦\ùï³â—¶ãNùáøÇéã%ì´J'ˆ•šv´ÃL“>+zV²ÅSäQ^³_öN o$’Ô©¦•‘-¨‰q¡ãžÞÁZǸƒNhjÔl‹'$/:ž2MœO™oâ„§3ç¦f„E.xþŽž„35-+¦°¤xѱB_¤Š— )DÓ‚çœsmªãH”™é †µ®£b#Â×|‰IÏid#MžŠ9ç6*‚qw$ð7»Ê Œø»xë zÑ ŒORšp漌„Bn‡Þ (â\ N¤´A PTS Ç9 –º˜†82Þ^Õ‰vu)Çã.BÛÑ?ŒP‹tK¹àC‹núM%gIG=ȃ[ME!.‡"Ç]Jp@*¿—–î$t••×鮕„o’“݂ߪ[(aÒCdHÙ\ŒB°·£ê¥!|{%ÖT}‚pެ2wïy»!I¬ØBFs…ÔÕÙmT£P•îÔóØ) Á˜C‰%5q.´¼ÝmÞÇÞSíÚ8³ŠñUØ^†œ|*•âjßfYÅÇ;-C@ÄЂMŽeR˜Ø8çœëøsŸ5ïÖ|C±êeb«l$¸p&TM]5)Ö„¸ê3ßÚŒÕ>¤ûf÷pnûUcÊXì¼gaSñì “ÃQͦy溽)äÄF¦^xt«âÍn®.†ÖTœU]°¯Ù_¥/ÄŠáÑ<æ3çŶe‘W\¼lÓ·Øeû{ÖŸë=˰ ˜-ÚÖÔýº–i[jîuÑý² :”gˆ¼(e²r½ ¦{gÍmrDÚl‹XÃï+ªÏ‹¬·èŒa›§˜rµâIξzöšŒC’ËòÍ–|¡¬.¼*“—ÿ™k[þ^±S]ìÙ+óìºxß ³ïO9MsQ^ºa>Zcñ%«¯‡â5œ¼@ ”‚Qp7æœË&fpÿ#`ñBšÔ®¼ð¯ƒdº™^!ÈÍ]Ÿ9¼?&†œ²Z¬ö£ÎÚø§ñYà endstream endobj 6 0 obj 1138 endobj 8 0 obj <> stream xœµXKoG ¾ï¯Øs«3|ÌH¸@niôPä¤6-¹@sÉß/³O­¤^lÃÒp‡äœu8ÄþG÷oú§pÀ>W<”ž+ËúûŸýoïúºØëï÷¿º ýk§LÙÖ—Þ×" B„yá»w_ß™rý ?Ÿ:¬Âo§?úŸ^D5õ§¯GÃé[÷áÔ}ºâçß®òÓ1Ý ¡Ê3Š1¯$ñщKoÕ(ê.}ãiC5Æ•Žæˆ›õë/fáùû(Ç}{“Ó>‹[Q¨ÚSʲ#zc‘u1ÙÏÝ!€""ºQ‰õˆ BÉéB%Ù#y&Ô‚stèÀ!ÖÔo¿ÅEc‰ƒÈ¾v±ˆ$UÑf‡ßÓÈç¨bŠ&Fj± ”Çh,9›£ÜbB ã¨ø¤%º °+š HÉÄ5>' I ÑøÌœÛ P£±‚]E,(ëhn,®"fÝF»_ebzÉ~ÛÅQœì~—œ»Ib|Ä,\zúßé…0•!Ós"ù¢:<Ñ1}¾œ>îeO³›·j*áÀÇTF5/ª&³,3ͺ®+êÆkÈ'$|J ”nRwWTc\éxXopÚgwë>Î0PË9 ³îΔµN8CIê:á Cly8sîã 4Ôp%xgºΠ€ÁÖq5¤—œÛ£<ÿ€4î©Le[]´€Éã–v(Š€Á¯ jB Î’óÚ« &BõìÉú­Õh›?I Ø5ZÉQõ@-Ô?@¯KÎýüÉÊméz?+à?ÊŸªF îäÏ* ÷óg­+Ö"ÊØÂ×Ô¹º8À1KõOuˆÇ”…“äÃH[åá)JÏKÏú¤ûû:È™(P]¨â–øÖv]Ò˜IHzÛDA&b J䩬ÁdG}ªÌvn+ª·c…ź¢{­g‹UÆ»’šë:uÌŠHÝìóìe¹DK:"Mr§.½S‚%] YŽXSs¥å~Az›ó”$.Ò&³V×.¡‚‡r6µw R"°Q@OAI>îIÎÔ®”´A™/´.9·þ'>®V#¸Ú4ÃŪÉ"q¹hñ cÒ¤$&S­”bLõÌ·=†‹\Š>ňy²®‡M1J2ŠóŒEkE48ÚÔµPÎ\§Š„Z¼È€§¦û89\lŽ>q›;™Ï6œH ©æó̹[ª8ê–iWMúE+ j­Ò’E÷r¥Å°šo·z×òJ±Yé°®|–Ê‹ŒÜ•bؘex’£QëeIµu1h¬à4ÎZà¨xËAáHÖrÐg r²1ÕµŒ¥¤Vá›mø,&€†J4øÏ\×ð7Ä6\f™“!s6Sôé1iqÇ„­Â8úuËv5qÇ1 Ãh! ¢`f,9wa“]¸½0¬nˆøÆý€¾I ÓUW4„HlÞ{/qòy@j-\|I¸so›Á-[E°±!JhJ£¢´°€¦i­‰rn‹FJ¯Èå1kaq;>w:`£4슧£U\Ÿ|ÍvŽS~êe¢ŠÍ*ïvºf_ŸWþŒ{ã±û2y©ÉkÕ|n”Ÿz™(¶éMåÝN×ìëóÊŸ[M+Ó~ÏhrIMïÓ61oÔñrC}£ A{bœÞ-ₚ9÷ÿס@f.ímàã€Ñ°çáI¿åÌiõ©ÿ×f‘„ endstream endobj 9 0 obj 1358 endobj 11 0 obj <> stream xœµXIo[G ¾ëW¼s»3r@ÐqÜÒè¡èÉmZræ’¿_~ä¼UOVuŒÈC Éá¾8ÜÇáÛáß! wá> ¥¥û:H=ýsøõÝðÏ!øùú×!àbx9©Øù<øYiI0üöïÃçwÆ?Êá§§CjŠoO ?<*kž>)œž¾Þ?>^à˽¼Nî[ˆ-ão6†¦š¤’T —eÕÓó`·¨,ÏCTxuÄ®Œ‹öËÏ&å7ýÿAŸûò&¯}RÕ¢Bmà\ôFùƪçj´Ÿ“•ˆª’࢒à‰B éë e½cýN¡æ¨Ð½tã­«ŠD¤Ï²¥}9Δܔ›=~… –/dŠšŒŒ!‹ H…“d,1o‹l!·qDŒrŒjÝ™ 5!©ÙÈa؉CVA`Ÿsëp"™+bMzަÆÂ±à:™$öZÜÛÕ#9›—˜»‰bx,¢Xø¤ 4ð;æGN¹žò1?dÖ_ÜNw|ÌïO¿?}ØË F&·lÙ4N'9æ:²y›"z,<óR;6ý§ö¬cbµQÝÕ˜°IqØ9VØ`Ã5Ôñ ·דêÿ}É ~ö RN9ßË6¥µ¸(††œŒ%˜¯±Þ‘§÷ó2d‚>¹z&äwäb™° šÜ ­X`kž={¤OK/ ÌícQ³ZTåÚc<ã¼OOiT³i CTm̦–W1°™q‰w¡U„-˜cíj³ôYé”Uiý^ºæ4Tq•64vÿÌHû)´¨Å"_¤vÎn¯„?ò¨!b¶ñ¯ÑùiÀüXdøk.±UUZÞè|ˆO ':æ¨Ek·rÈEýªœî¢¶) Ê>‘„ס:5íbÈ]P;ë‡éti‚©êt§»t­Š›` CÙ»àÂ…=ÁÐ¥œHÅP!g¦…ÊòìtYñ¢X£µfÄCçÁ! Áâ=[.®¡Ž¹âòzŸ}›÷>y»Öx¤j“²89äCr™’øzÛÉLÖˆ‹%J&„9ë›H@Ú„ŠçÞs«NŠ'ž¯Òl–jíi‘mRQÇôÂ0 °xŠBÿ'c=ãmŸm̪eôBÅÓóERç„rˆf\iÞŒÃí!Cªuñ೉´±µ²él£–²f:Ϙ»UF"®0"]´È±ÌŒ%â•2#ZrÅ-×m/4»v͎Ť.¬š,ÙiYHñʨÜi„6P=Ýéà ŲæÖÅ ¶Èíõ3’ÖŠ$"ÚJ€(ÙZO 08K1g=¬–áb ‰pEðfI6øU#H“É‚ƺ ~‹×•E§´lq9‹rôÉ-£>§œzK¦qì:,»Ÿu®q„#‹àdá™"X…Þ gÌÝ AûK൵5\X®ø‡0Å'ዉÎâCmó£WzN‰ûPƈ©~ÔÛK¿m§bõ„È 5Mí2ƒæéŒ4yîP²qž ¸ÈéSAYqÎ~~V "&‚Ù QŠVoA?žÅÞqÈ_=Oäqz—Ó9ûùy¥ÏX¯7».“Æ3´ße2Y_VдyYÃ1:DmÜ6¦9Ç/z„jƒ£4®w¨Á34cîoƨZêÞ¹ õFm)¯íøŽl¤Ðy¢±^Ü#Ž4îOEes@Ý QÄ– ÔWí b Ü—eØ3×å[ "PÛ´ &}Û´ &íP<-ˆŽ¹¿ ê˜Ö×eüz±XøÚ‡‹4-ˆT½ú‚H-XÑYb^Ìú¶8—>ÆCâMùõÍD¿îûrB.JßZl‡!N=sg̽FE¤æk¯í0ø3ÂvñµÍ„¨§‹5$qé; Ê@ßh˜ûS¶•ÞËÅwµ±ÞZ|„Hi§¯öçïéÇ©šßãåŒð`¼Ê÷Tex`,0CíïAÉþp3žc¯Ê€¨&_:lã4OØXêœýülqÈrß¶¡Çq§ÏàüÜ!õÿ »FÈ endstream endobj 12 0 obj 1606 endobj 14 0 obj <> stream xœµXËŽ[7 Ýû+î:À¸)êÒÁLìÒ ÐEU-‚™Í&¿_R×¾/$iбhQ)’Gû8|Ýý7„á&ìy(÷u&:þòqøëÅðï.ø÷åï]ÀÄð´ƒR±ñãàc]K*„óÀgÿÙ}zaÆñO-üþ°ã¦úöçáÃðÛ½šNÃç…ãÃçÝÝÃîõJ_öòü‚°o!¶<ŒŸæl M#áÂêÐÓŽ²ÆéÂã`BjQM>QH ©+Îlô`ܵ?ÿ0/¿êÿ¯t»Ï¿d·7ZT© )Q»±ê¸ÚÚ7»Ó)U]‚‰fJ‚- ©¤»«”u.éw*M4Ç€öÒoþ©!‘n›$èÚ§]¬º25µf›_X†“/ËT•mY‚IÌHꜰ90ÕÜKËpWDµìòI èå¿=äûĹó!ßæ¤©oÒ!ßß=¼ÚBQÃi(”–fZâ£rÍÜÃL–t¶¥Á5ýOƒ¬#¸Š¥ÞG8‚±±0Ʊú)E½f^H]obàq÷<°~îN*À/f Ãñ¢–rÞËV@.&Š©—±C¤¤säŸh.ó„(è61UGCÆc*††Éf17S+–@Š5˜Ož tkéI3Ñ\nÙ¢!{²ô‚c}`l³3aˆiDùŠ!Ù1NõVQEDЂ`,8»ŠÈ1e Z¿—9 Uü†JZòû9+m§Ô¢&L^¥{΂Ԟ?ò¨1Kü+úa#ß" Rº/2þÜ UTaIõl‡’Ûá¤ncÿÓðçßýCÁ¿­:.Lw…u$,V:ÞP;ø7T©Mo£²‹AŸk´r—îÌ¥ÇÁ% Áð• ûs©kά<_ÛÍ~o¼®\ª½Rµ0®žv™ÿTNIs¹öæDVü‹3`•tO€RÑ9ÇúTsfÕÏiÖ¿¤Zž [*ê†N˜šR‡4$ô2Óg½å6¢Í@£ŒÞ·Ô=¯’(3ò&Q0äJ";]Âá¤(–8g­ëm-3(K ÑW¬5¤®76Ñ:TL5ÙB'&ÙnÅ)SÒÒÑ,æ³æfVKÄÚòª%i=¦ä3i-ZâÄ6-—ìÍÆ67—ļ.I#™š;Hàxžõ5B ¨otcFqª¹u7f¹}îÎq:}±Ò/h+®HLVêKÀ')vÄÙh‰Ãj KHÀàÍÂF6ª-`Ã$øÏZ›÷ƒÎ&–+óÀôf’\8 IcI+²bW¡n¼TΪ·àâí‘Sç ×"Õ‡:{ázÓù3dzõµëA‘-·ZIõS¿ ñ |À²Ý•//hœ9,ã-”ká ÕÞdBÔsØnÒ…ÎP˜½j9'™K]qfãÍþù»])ÄN)È8èH*HòÈÁ/W §Pmfo;Ñ êœü¬·M3ˆ«3pëÄe,Us¢ >1 böà•jPò®3Õ»L6X+cúQ²-×Eé{Ø£°rŒûeiÑýáFágº8ëìÜU÷ì·æi["ëÒ¨1s©kά\ã¿b?@S¬{SàÞÑEç(¤%YÏŒ.KÖ  †&OÁŸŠôF‚¿Í§šßÒ, CÍÆËÅ^±Êu&"ŠÂdª±wY\`4 E{®À…©æv³ÔŒÕhì™øcÏ@ ÍÜhë¶Û–¾©a¦fµaE«×Ý\Èy•#T3™Ò=Ùì™~-Êw¬0”îã,Ï»$¥s£+–Œ¼ÄK05Xfí*Vl‰¡%Äꬷ¦‰(Š@R5'²Õ¯ÑÝÀ+ N±=øñ«xb»ùÏÓ—YÌ0¨åÎj-Á”ÿdEÍæÄ"™j^±ænÉC%dž–â«Tšr²–ˆe ”Š@*ÖJϨQs}FÜ/ œÈ&¥°d¹N1‘OÔðÈ'j‰ ‰'jéš+BÍÀWÖʊׅåó×Y7“ß¼´¦n¼ 19ö'šßpÈ–ÆÈC`Ü5ZÉÕF)„·|Ü F­TTÒsf¢µY%ÙiaɾÀŽ^6{x%ýŽN–*ª3ò6)ÝFfÎûB"´nî¿~tM³Gȯ­Í¿ï5O–QbËw¬§Zm\Oã÷»-Wª¯ÉŠ+ÚûZ™¶}·G›Xå¾¹5¿ŸÅ0v¥E”=–åDÚÖ7_Ì¿§Éxª;)Ùl$´»ž•Ê[»ÏÂY oVÊÙÎÃÛA¹MbÞþx§ztGüàb}<=â)7pf?Ýl)3“\k\9þж@²>e^«ùëêõð?¡”Í~ endstream endobj 15 0 obj 1721 endobj 17 0 obj <> stream xœµYM#7½ûWÔ9ÀôJ¤>Ã@ÒÈ,[vØC““ì"è°¹äï/ߣʮ*—Û$3i‹E‘?žÔá)Nþ7…éCxÒ©v}jSîÙÆ¿ÿ<ýû«é·CœðóûÓÛL•ã×ÉǶVŒ×Ïþ÷ðËWŽ“ðÍËA»ñó×ËOÓ?>šè4½ür”pzùõðíËáûþü”ß_žzˆ½Ló'•¡›%ZÕz;H1;xH¤MäëÍ€´¡ãJÆ0ÆUû×?©åöÿ;Ûî×/²Û'3-Õ§TªÍ˜ÜØlܸöÓáâ%‘fK0ÑÉ”±E£lw£ŠÍ%ûΨçlÐSÎ[š‰"bÛ¦líÛ!6[™ºIãæw–Áó5b™±*—%(2eÊe¥KÎÝ`éêæl\<|1vø?ËǤ¥Ê±<—d©Ÿ>¤cùöôãËw{QÔá ¥­˜žô”¥Íb>BLÍ6¬é*ËŒëöÏŒlspU3Ê´p8ŒáØŒqlî¥hǬjð-¼Þ¬¿w'•¶ )±ió@VA…ÃGLrç¦ÕwŽHò7[òmsDbµÓîÁ-j±]b|µQ,Å´µï3™ºÉnÙí¨}êÉ­¸2í Ø¢…U¹ ë5VR'Hm~ÝF‰Åd”gKJk^†ÇZФhrª× •ärâIŽÕÜÆc©F™2rt’#|g• ±Ì½ÚéC´%_÷“…¥ŽWkÚeõ3~%#¡¶I`•`Ÿ '@l.oÔb- ·"a,X;m·ÜfÆ£¶È”BÄ©×É©K@a@®©Á¹’ò~Áý2û}òd¿Ws³jÅ0~;Ô¦Z)öÝ‚X’°"WæADq²=ã ªÍyj-9·ö5¾ìé˜;›Jn,œ‹dÊ–:dB§HÙ3Pô•o»M¶ mVFo&¦žor¶(Ò4I R3 ½+pNŠ™yzåzÜkŠG¤éÜÌzBxÜmr.ô&•Z(<Ç1É*U§ÍWÎÝ"’#¦Ð+oúÄ\Eæ ðNÉVQ37­÷»Í¨#»Ýf-.ej]“Y²wÌAãÌ4ÖdÙ( VNlcE-l¥5¤/rûRºÅÇÀ q™#¢­¨’c"L©O¹ÒÅ…XÁÃj.LH„+‚·d%h\ ŒIeð_¹vÏ'z–i劤)ßq…  kN7‚Gaj|íÐÉ瓦Ž%7ÚìãQD˜Í_Cf{«îóé>í ™¿˜‹|¶«Þ^ѧKØÚ[¥´ª ü» Odä0OÒ‰T½j9PXSƒq%ãöýûw{PˆÁáŒa$—߯ŽVÀÚªso¿ É2€ò•oÕˆ6‡Åì¢u.Uk\ƒ ½Quã Ù8N˜¡óÝÇ6j•1ýUlƒ-o‹ÒŸ7ŠÂª1>mK‹í5ª¾ƒš³ žÃÞŠž­p®SÖ³I‰µ%a—FYSƒs%åFøû!43»·=Ûœ„Ä®·j“è²ÂV64y ~e'ü¼äüœfPZám3öÇ–#‘lQ˜ÈG—ÅFª*ò–œûÍÒ2Ö¬áÝí¯ÝÍrèT£ß¶Ý¾‘ôY 3uÖ†¡» µÜ䈴‚A¦ Mv{¦1nDos5ÈÏ]RÒµÑU&£nã%Ío{ź —0ZÒ ¬®|·0E‘Ô¨Da æ…1y­RÞÂcj”)’¹›¿E,/‚±@ •;ÖZ(GÀ¢Î¹LK–œƒØr§ä¦ 2ÏJñC(­ˆraKÄ2)E@U6…:2jæ¼õ‘ލ°))lQ®FL” ´Dx” ´ÄÄ ´tÎ@­ÀDJ¬l•· ÛÛ¶£n?ù\ÑT†ðŠÄÔ86^p~†“™ÆÄMPœ5ZÉÃF™w ñ8CMze¨e3TfÁµ[%’ð…+lÑБÝ@q%$ý,5TgeäíBºÌ\÷…$hÝš;óP‘òÕÄÄc¶ùó ¤{²Ì`Ÿ¯—Ö8n—ñùP"s¥ùšbàc‹ö±ÖG俨w{õ1µÀ*×Í¥ùø¼²aîJ+‡-ÃʵÏO]¨ßÛb¼ä]”leH ZÏ@W¥ò™çYµäª»•rµóôÃdØ&©îüh|?ÙŽxßa£W\å&-êÞ-L™å\óÊùõë]X‰rKf¶HD-DãÏa%b`F€’Ök`š2TdTÌ+ç °<‡¢ NËóåá,)‘lÊšî¯Æ L|ïË Î¾¤¢ÈÇR±ŽTduÊÕËÅîÛ2[œð}œ_Rwä×ÈþSu {Åѵæ1æ> stream xœµYM7 ½ûW̹ÀnE‰Ô`HIÜÒ,ÐCÓ¦iìh.ùûå#5žíÝ6É"¶8CQ”ôÈGÉá–†o»†0Ü„Û4”–në M´ýõá÷Ÿ†¿w4àï럻€ÃÓJÅÚƒ·µoT!L û×îóOfjá—û]jªo÷Ÿ†Ÿß¨iî?ïc8ÜÙ½¾ß½;Ñ—[¹Ü!ܶ@-ã·9K¡éLRIêÐÓ.f§ ƒ ÜHM>¤à•Ô6údܵß~5/¿éÿ·:Ü—2Ú{©ÔÎEߨ]ªÚ®Ö÷ýî¸J1Ví‚Í”C”¨’Ž®RÖw¬ÏTšiŽº•¾xËobŒQ‡e Ú÷iGU{rSk6ø™nXùB親ɺ1`1 ©s’̹æz}c„NjÑfN5i›¬×læTð:ÙrBI€­Z|q«'ÛrÎ57qiz,¢Z†³¨göù §\yŸï2ë·Ã ïóëÃÇû·[€mÑü–µ™Æé û\G3o`¦ˆ6 O¶t›þÓõ¬#Ž‹®Ÿ.ao±&ÖÖ½D›ªoéÄÒJêz3»Ëþ¾#½÷éœC) Eû8°£öÔö¸ÁçÑå D¬˜›¢än’6Ïæz'Ø¢¢(lA5%«±·ÄVÎ:5}.¦ÔÔvŸtiCcŸò¤´*¨‘Â=Ÿ  ˜€Åí¢Í†MXCJùÈb~SdŽ¥U"A}ÎÂ#»”épCêÇÁ>– û\ôCs-°ÕÛ¸/)¾.IÇAÄÃMl{kls4odfñÈ®d銻æÒãà’„`Ù" –R×\X¹œ›ÌxWÐ-U›!ëi—SDn)ÅÌ^DwæhÉ»4s°XÇì }çhŸk®çŸ“ê‰Gˆ4ã©–cgøEsà S©°8¨!3¢™žôÖÈ&s%9ï¨{Ú> £œ9ƒ© Z8ÚêF,“XèLZ×i)'”ÈW,ßr׉Ij´ŽÎgÒF~`›3JÖäÑlΓæf\ áhõ$Ï=å…ÀM{bƒ–ólÑC{“-–æXÌëÂ:“¹¹½„DgÊ«ÞGâÊX7:pBzª¹u7±½dêcùQK! ­¸"ÄFÁ%`ÁYŠ-q¶²Âa5‡‹$à ðfIV,Të “ÉÀ?imîe[Y«¥KÁ‰åÌRDYIø¤°­P7^ytñ8c[¤zSßžKÀ@˜¾Ÿ Óóo´®¶Iȵåî˜r%èP)N)Ø_©jB£Å×ö4xÿ¼„¼ò¨€sX/2½½R_#óÄüz½’§;¯–RW\ظV_ÿÑÞŸ-ò_ÒÄÂÿ—­#ÓFL¿ˆ®‘—Ñí:2u|¸QÒ…¢Q"Ò¡V@"Ë-V\ öt™-@—’+ÎM\£×ï=6FŒô:‡åˆÂ>‡5³€˜ ½P-fÏ4”ÕÅjý™Ús¸%+ÙyB¬Èå0RÚfÑòö‚Œ¤FvölÑè׉uRÛfE(Y{‚B$ŸòF͸2ô,baÔ!Dlw Æ­®¶"k‚ÉÄDwe“\T ¼LÎ%ÄÞè"Gî|€ãå(­02ª)HÜ“¬Ê۵דÞi5ª¿f£èÊ6“°‰…ašáŒq˜meípÜŠŽ³o‹ŽJ(vÔºŽP Œ¾º $Ï(,”ÈnÐ1Ú†¶^XÂ'"?ÅÍ5O—¥W+r^yµ|ZXÂ\ËÇ«Å^V‚©WjG­+Ù¥"”)VÈ]’‚–l Æ6Vñ¡Kv·òØ;ÞyoÛG7kÍ›U0ý¬ÆM@•‘¼«7ÍäC|´Ç£?¼³ûçV½ý°˜Çœ|f3ísg:IÛúݻܑ}Ž4¡À¢"^í‹qÖ=Ù-<Ô*RÈÎúÁ¢B vŽJ´ýšôžRËt䇋d})õËy4â˜B’æ…ÉOÏžµ•ÉÝšimæQŽØ(Êé„ÈQd½jvеúö¼ÎÕø«ÊI*ëõáFöZî«ß<Äl‡ÝI—Ót‰ôÜUmT½£Ô/̺Ä(aú$Y Å좥X&P Úˆë`-M½µÌÖƒ·[¯­ã8:ú¸OnÉÛ ß·ñè¾g7“Îà×¼Jýì8¶· 3IÄGJ ¹³},)KI›,²yø0h…Ç)m}T½O:"¢ÏBGÞ|ĉðX@æL³*Ô¥®vì<]ƒmÞƒèqµ\Êl•ªI¸•°*6g§Š€$°”ºæÌƵ"í{…iå*N±§ãp¨¬SL9R°ª8eÅÐOÝök@¬ýÔ]ÎP°ßAD‹½'+Òœéôð˜ŽL#N±ÏëѪÿJø™æsªB侨oᥩ՜¯_U"çWS-ý"FÈÎÿb÷±8ÿÏ5ÏÜ7 õ¥6®§_r߀‹Hô¿ÝM¯oìàeÕìº(4cŠBïJuuQ1V…ÈÆ¯p£–5CyEf5Xö-v \Äv'%à·°­*~ûÈ`óFËTŠ’b'K0ŸQN–8´þ3Τ¶ý»V¶ ¡¼*Ý—w/L˜' endstream endobj 21 0 obj 1958 endobj 23 0 obj <> stream xœœ¹cte]·5ÛvvR±m;UìT´cÛ¶mÛ¶m›Ul§Â[Ï{ÎyÏ=÷;ߟÛvk{­9ú}ŽÑg_ëÏ"'ù¡L/llk”°µq¢gf`âÈ›[:;*ÙZËÛrËÒ+Mãpää*æNVÀÿ-Ž\ èàhnkÃó_©¢@§¿1§¿*fÎagS€ÀÌÊÃÌÆÃÆ `abâü¯D[€‰ƒ­!¹¨­»ƒ¹©™àß·*U%ujZZºÿŽ0sss Ýÿ ˆÍMmÿƒàoÔhekg ´qâˆþ [Y™L­ÜíÌÆÆ@ã8Ô ¬€– s+s;;[•(õÿdùÛ(3ýß?v8r€$Ðèðw¤þ#™„­ƒ)ð_³0q²°¨ÌœœìxMþB&ÿ@ Ž& 6@'Æ¿œäâ6Æ¢¶Öÿtã÷O±˜¹ÐèïðîŒÿ‹æ–6¶®6žÿbbncüÏcg;FUs{g ´Øæÿ ÁýwÌè`gbaâfeí@7#3Æ6Vq·þ üWØÀÆØÛÓÎÖ`b`åô67þ½Ày:¸NÎ@oÏÿ7ð?WpÌÌcs#'€!ÐÔÜî¿Ùÿ†&ÿ±–3pr0wh31üUÀôÏïßwºߨ֯Êý¿Óå ¬€ÿmîgˆˆØº<é™9¸ô,\Ìf¦¿óq³°¼ÿ'Û¿uø/ þýa`þŸ=2ý7¥´‰-€û?Fù«áŽ`tù_¨þñ55àðÿmÒÖÉÜø×2ÿ6¦;Ó_Oþ½0ÿ¯†ýø¿mûÿÏ©ÿp‰þÃôßý?:”p¶²ú— Tÿ!(௢6€¿¢dÿ¨jeàðX›[¹ÿßÊþtuà<¥ÿ7:i'ƒ¿ÓÛ˜Zý—äFsG s7 ñs'#³ÿðݪ6Æ@+sà[GóÞ zf&¦ÿ/¨bfndittü{´ÿ€6Æÿs[Fq#[csS€²Ó_ƒ8ÿ;ðläìàðWì÷ßÚÿZ›˜ÿítÁ9 ¡ßY•iå~¾ýhê¤d¢ÑTÝú¶{Ïí2ö^Œ{hGר‚}Wªi=,, 4Úp² AÈ/’аì¥Àú/€XMŸ„}¤ØO¯^¢+…|—1êKñn@eÌ޽ÍmÏEª·¾Ÿó“µÙÈIJ bûäJt?ð¦c¨jÑÎÁxcãEËCC¬¦Úôù‚A¾«ñûâ£Lo Æ‚Aƒa»ùèòÛ‡S¯µßz3åû´Tí½hïá‡ÉeƒàßeÍääßÔU:É-SüÈ~*íç$µbEÅÌ0X¼Ï}Y<3gW›«tÞ?/} ñ›··šÓÌœpû•^à¶ÎE ¯¸½6:°¿G¿R¾j’J>sI¬s7>˜~m0¥}¤R¤†'HwÖœ¬…Év)<ËñÁ+'Û±éý–[Àe–&‚8#sYÉÉhýbÑ7öû‡ÓAž<äë}ƒÉwhÐ$æ‚=ÈW4ø²Á³c¶ÞU\-ÿv/ˆe.eŸ ‹á{µæ®´ô?ën_ª‹Ö…އrÒÎü—×'à GmJòxüü”IÄ7‘¿Î4·ZóÒ•¥0ìrC¥Ú•}Ì¡}ŸëE‰öÈbÀnzRT¿iû¼3îü›–)‘ìMÎå:Èõ/9Ÿåª‰_TÃݲ™bºD d¼‘iº°‚#?¸A4‰tP°ï±UÂÙ¯%•˜]7_ÚÃIn’Ð-rb¼…)~¨îšÉ²E—ä”Yb`*KÆÕo¶[J¯ÌÙ0AøŠÇmoÑ"”-«LùG´*øuU>Ž-C†ú6ŒÞ£SŽKj0Ö¡üsv‚i ™‡÷—î.ÔlœIù A¶žS€ â½ l¡tÄÌÆ¼QˆÂ#'PSfQ9!•Ö!¦_ «ÚRþML#Þ­æMNzÅ"¬Ój 4)€ŒÀˆ~þïE5”¿Ö½ÉŸ>ŠŸ$Q/<¨Ò«Òº£ÃÜKÚH4ä‡, £}Kq'ïž%™FûÞ›_œÅ5Ñ·a#•öÊ8¿¿+£rK þëÙîÈ3¨ø¦[>±A á]P!ªtŽQ>¥´Q‡G¨rÇ´qXÿú1EÚy¯[A»ÎùÐT,Ýi£R%^Õ̱†óP‰erÎûÄ¿‹š]÷ÈIˆwhní®ó†¤³Øw*ê§cÈ›G'TŽÍƒºórEÓ³ 5ÈÚ-ø¹œvµ3í9SÃgêב{êâ¿ú0,€Ò4¿^CË`^/¯²h5+ÓB ^~],@8Æ=HØço¤X®_m.G×p¤’D™íͬöi~ «åÇŒe}ê!¦1v.Åþ ŽêôFkŠëd£ª— Øv¸×ÜÜ׺(ˆ² ©×W­ì˜D/\ÝöæÝ˜œŠäüõ†Î$¾ã:’ØǹÀ÷TÚa:vYš‹u‚k46 mÞéôý,oUvÑÇ0éÏOØâ+ŒêhÒÇ™<+¾ÒËÉÀ¨Kß×ýÁß%Â¥Y›Ûz½Ð´ÒÔÒë.}=û;ûq¡~ů“¼–0”ž:ÖGì3ાéSÅ\qÝOxk ¿¤;'nº°&ÈdÚW<~gƒ•Ž¡Ð]:æ…$¹Ô8Ⱥßb±_ÌÓ í¿S‚8Õê` ¶˜Ãè\¾¥öá=¥‡ON»ë‹ùÜ€íaD~,$AkäLüiÈ£^ü,nQcÛN¹Áâ]Vª;æI‹]ÕWm¥ŒÚ¼ëÏhßo‘UÔJ %šHÖ¯f”R&•h Šõ¹¤+A-CE-Ñzx§P¯ÞþÍAÕé„0EÔð[ÌDàÍñlÿŒ¤<-¿ÝÜ“ûœï‚®¹4ÑÄ9©«Èü Ñ‘ŸŽ"¢òÄfkoTo“9ä—ûã», ¿0áì×g{Üc”VLY·‚ TzÎÂiRÊŸ‹ìZ\óöç)Ïׂ¥ê=þøl /½UÌ9!¦Ê‡½Ô¶ ‹ÓôçÜs!í°ÔÉÌ;?¿Qdƃ#H}MÎtÖ×"N@t“äõ釩'‘hõA‹OPSè°y­¨´óŸAºg¢ÍÉõ*Ý[Û’3í"DHáCëmЫÆèYv$f_ÏŽ¶Õæ+(Íg†pÖÎßk´•¸Ü[»ÊÂ\­[W¹ËÐ>æñç(Ï·uª6ÑÕ8_.”‚cQ]µiaªo‚ÁíhnÞý¯–"_Aíw¦8!Ìyçžbj@&Š Må¹Lw™ðµÃF>HòÂXh×e4­6æÄòú"iXdÙµ´ ÙO¡þµ\?Ì%ì0ÈÁºMl\Û“!1žZºU‰mZW Y年!4ã±1Ъ¡/BÿXoƒÏs&‘Ú-Šlt}­ö(‡W8c“hÚÚ;à Ô~ £ õm1„0áPUyûÜ (ú×E²›+Å`îŸ;ñ5 ñ.™ë+iÃU{J„Î8½¿¦‚ bOœKÌ#²™ó…ÆA¥_lpßk&÷ˆßs!†¿ÅÞ"¸3pœ$†ðÕÀši|âH\¯B'ù¦èÇOø7•+gá/.[|G9ñÝ»ðä †€@PêG×ÓÇ?Ï5–³ %ó~âšI,¤7\)òÕÜ"ÞˆB_CVÖÕ,°´";ïRhjvž… Œg]á÷¹H} o‘MGûÂi²TšÎ8²­$~ãbP–7†<}>S§f,!Mö(Ö9ƒI§˜^«š4ÚLŠ»‘ä"­#hþØ+]辯-S^4#C¬ÎËTÕa1+I’W©ï©[haÕÕV$¨ŒQçjYsqê?âü ¬›0¿0‰¾3,Oiÿ4ETê´À&7Ì$[¾ä€F ¸Ðm»¨³w=žÐ(½ï¼êLÈœ>ùy1¿þt¨˜®£ƒm4ùã)LJœXrý»ïñ½@Ó]HKÎÛÙ^Í\Bù§­È9…Øçùh®èGµ˜€Ü£ŽjhdpjVØ›¡Ó–w ð`G>¾­ŠXEÕõu4›["‘ƒ¢°ÞÊäY#CEþñ»$šVà2Þ$!÷°?áÝ5ÝN¦•kì…°ÐT¼wP§ÿ i¡þÃö šb:]ĵچ… }*MÙ½]Žà!(¯†›7'HH«I¥\#"ˆûÌ5á©¥ØÔ’,›xöŠ¿èÜúË¥•ïºÖ•qªO,äÁ2øö·uË>øAZRïvÅFÕiÅfqõÔ%±k8Qò¶£CóÞ®ÖGÃ\ƒ¿€ÎÁ—I”2Aò÷ú¶s”D:¿îWÌùÝÄxTÇ!‘ƒÐSI-éÆXš|o=?ŠS,èëû¢Tê#ìÎÚ„ŸëÚõO ‚’È·E2ñ ØËжݴ˜·_ß9æó¢ÛÐò¶ÙY@*xnksªèõ™) jŸ±÷­t6Õö}Ÿï³´Còg•ŽDª9%ϪŸ²^J*îsr/¥a_–ÀŠº–DZ£3iÚ Ö²’ÒW™µý”¢{X“²Ý³VÑÌLžýNg”gE9ñÇ2 &JS õíónÈ› àÑ¿ˆvâÙ[0Þ©<—Ì)N«²|Â.æ lK{mšúè7F"ó ¯(‰¥_I묜YWÒ> ~ÝÎÀA®E-ɶ«çkÒ§e‡é&£zŽ>}N)„lÏ£~ŽØÑmòÚÿélÇ( ¶ó½i½i+µ°´8\ÓrÙB3õ _,¸ªÿðJ(s©®;KòÏ9<25/”ö¯qÙ 9Œ¹åg=ò³Ä/ãÞvMûŽŽó4ZçÑHf²LØŠ:ø›ŠœÌÃl ¹öìs$‰Î›Ö›©pXÆG~±w~/d¬×,S}d+uj¹ƒŽÓúœÎ £é2±\p']¦Ÿl07ÍAÙmqYÒÁ²‚‹ÑsŽÕ0ÜqDÅ~»®*ë¤Mjt·ÏKŽ'ÅÉ&àáŠSà~š#'  ‘Vc º(ú¥ ªaÉSÄ!xŸ$"} ­Î DvQ—Ž&n 1ƒ •櫹 ¿À½:!èң˂è'ûqÞµ›zã¡8ý¤ †ÄUôç*ñ6fd2~T‘§)îsŽy~)3ÙHŸÅ…Åì\Ñ_@ëÉA—)^Q Ñý¾Ö,ÞÄOgËeó R­œ™(;;AK²f£“ÜÁL®æÆà»+ÑÏ"¾G÷œ°_BøoR/½3nyX‡v8!Æ!”W:ÎË£Ï~Jæ*®â1x”Æ ‡ œv:>]Ž“¡&æÉ¬ïîãPæß´ šW[¬7ÚÎç`åï#Ùáã\”ò2«Sx ÷7k‘áe‰©6†„¿ÐáŸwúåqî³Ä/ ÁaÖ¾î#ƒÓc¨ ñpnµÈל”æðÁu[Þ£˜~\ÏŽÔKñ¯\ûÄ-E”—HÔõŸØcÆFJ®¶“ñï_Ƚn»0 ¾>9‘‚Ýf_¼ÿ„L·5Uã•;dìØH3ë¾€ï× ŽTqüͺô’«ülѸ¶Ö² †<ëâÒÛÝjçd=5RBPÅâUH¯=B€W4–aF”yæî¯¢cè`!‹¬s³´.`vÍP:Ä(J|]ü{¶W¸¼Ýi”HJç{Võ£½d ”bÆ•˜|Ðkha¼Ñz,?5«‚ÍèŒpkS6i-5ARľ&¶bì]i1ãÝý`£Yèpâå1 ðÛ×Qàv¤mY†›¦(J4é{À „ÁŸý†÷ ø`>q68òR!W^vž Ç[U^þÕÝGü{ ,8P]\âA^JbŸaš°CØîy{›Ko¿t×i4ˆýMNˆ¶T!v_{­ÀLï1 ´*âiǼŽR€-µâyŠQ,È0Ù²žêI}¾—U uð^u‡ZÕaûùõ¼b‰}MîâóF/¬W)ð„§ÈÍl˜…aûQ!&]1ñEABšÎ醯KOè3R-e°Àȳ`g"ãd+·ð‚踔žÓûQÕhd™Þ»;ü¢¢bøò=Ã!®› &èsØ­C˜#b½¾A|¢µþC{fÓ»¨õ½ÃÁ·mª˜·+8¿Ü‰ÆS â„ ã,(oÜ]ïb«„DÜÛ€´NˆêvÚÈRjâVÈáËÚo³`5reÞ¯·Ï'ù)mú¡öé Àfp„©$ß%ã ¡Ü-¹ù Œ0ê±C飹ÞX+´a’3=Å9„ýÖÞ|G]CÑO’Ìø1ó1|C•ÔEíâ#Ù­‚y t0{hRƒQE»››üÇ'6ázûœ3†Ê‰Í¡ÈátÑ-\îåò¨6Ð Xc 'Œ^ü†(Ò«¤`†ý83`ÍØÃ”ùR’äçVÞz_b:ê¤ÙqVÄI÷¹Ñågü“CëRÅRàt{̬4 -)ä -<3-–ÈÎ&]:à™>k7®E ¤Íß™zznûW"ñ¦é×^|˜ÔK"‹T*¯ÿÜk¥$%qå)Ò%R§Æ¥M‘ˆÉÀuµ ôòó0ô–eÓbȺj¡*ºV,è'ùiW7°+܂ވëÈ®Võ…-Ý— ~AÚÉq^誴Η¸Þ÷ó,0½‚᜹Ûé.AÖqÈ4Ö…‚BVÏàJY},Rqë$ÿÖ0ÐÅC‰-¦…õgÀd2&p¨‡ÄGÅvhž´ÌÎ*oe&‘Æ6žÔ(ÌåÙ† èK)©e/üV .ñv|›½ñe²X饫Â>„ñ⩳ÖÅ=Ã*ê§Ž-/ŽÜMc èV°àþàÃpV ‡+Û=ÑåÀ²áÛÛ-„Æh/çæråÇÜÃ)NôÉs„Ö~7W0ïŠÿ¹Ô'Uå&åQJ›°7陸Cåðùü¹„”£ßÑNªVk(NȬ¶ÞwTÕb¹x+¡qÈ!%`óRÐAVáWµåù~lÖ¯V–^“JXxå{§®å×è E0ú[L(ûoÚ̽"FYfsôþ\ˆï>†ÎRî9ß{¹9¬~k¶ü9mdÃ÷M‘oaí.þ®Ú)‰.Æm]Ó¨ÏЪ-VV{sÈ`[¹/M-˜=ô-5N×ÝÿBö4üVÍÊ)O mÃ=žlE]MȽt¬Øa(ÊM2ae|·$åé9¶ŠvÖôÓëB³ò#Š:wà€4Ó¤-«>V€-(ëeB&eyC­Ï¼øUåÉÄ»ª¶û£.»ÔZZ—æÞsE,Æã5”½î2 ûÂâE‹`±©ª”=ÖúÛRq£è±!ÅHqhÛڸ÷/Œ]”]yk;ÕfÌrg8%úÒoG¼‚ ŠÓµŸ¦ªd èÆo£hÅ¿²ù9Rù*ýkYutª†V‡´uŒ&qšg7õdRÁúçlëé\µ± àvñ¿;ò ÓÚÞkv|Ë 73–ŠzZ哱>= Fö}^Òúƒ’ð.…L’Dǘ_bÍ瓞/ÏÛà é|ä) 9­ûé¿Oóe׸:ôŒ!¼OÅd혅‹*:å\û†™¦ˆÎgØ.Úp7‡´y**,¿?#zK‡Úæ× â’ƒj çâYf8\^ïÿ‰â;ÕõcÑpÃt¬”H<~aç]ýCm¿Ls&Ü?æ {µ9ø.Ž"­:„ÊÈ2ae¤Ã®ß”&Žº³>§¥A¾Ö#ã?lâçµ!™=…¥Bðgճг€¥©xÖö›ÜÔ‘ ¦&›Œ”Q¼0;F™ß쀭 ž÷¬Î­nðj2¦m°‡ã¨»ÿú&_½ÞÂ@eŽ¥ú¹oK²H÷€œL–hâ»ÊAý^4Õ´3F`lvƒÝ4£tçáÂÓUÛdí\©Œ#GRˆ7xyL«×"_š~ð'ŠgÞ‡xž=·¡4\GGÄSð@‹¨Á‰`Ò¼þD²üd#­÷ÓæYz¼DJ¹£q3 ×Õå;.2»x#?É {øYÜ”áÌTÑUÈøÈÁ¥K²•Ç­¸ã†*Ò‘OÂÜ`åRÀôÞ€t]AK%4z§¥önæä“Òtï1câ@ÎÒi‹kO¤»¤Ÿ×±î"ò†¢IùWÄÌÆÇ‰õŽÅãk;àŒ•ÝQ¸a´ë#[Ç¢¶»7ËØTõw#A§´½^¶]Ý£¥¥/g—Í©®]øÈŽýjpX7¡œvœþ/¹eÑèmžô. <¡[ÎeÔ:×õD¨ òÞšˆ h0 „ˆb5oí·nÕeM²Ì¦5jÃ=ã E$]Ræûðâ!™5]}gúGhZÃÝ®ÙB©N NÝ÷úïG “phü Hjço4y¾Ï‹Ü|båÛ¼3bu;•éùâq7=™Çwh»‘5]„ë‹ð€KYmÙ>KÑŽäPóeŠkN¿Ã1©Õ.FçÇÔwâ×Û܉‰~á"ì ñ³‚ ÜaZÕov½ýÞ*u ¬ÁF³-·]UFø*ŒhÕõ ÀõæŽS‡åS˜:ô–c¦çE ­}ªî¶=nÔ±Nc®|ÕmÒ¦l!ñNÆŠÚ7ójoൠ Ž>€G*.C]5‹Q\åë^î“ÂóÁÇ S31ù¶LÛFÏ_ÐH“ Ì¢\‰ Ö˜K ,«FœÌÉç0É6"ÖWËoÜSg ÙD^§à\‡õÎn‚ÐR[ÚIt)—Žã¿Q¼°ýîzÕ«· LþÃ2Ê-2k3àÕíô*y[²J_ýÆ[L^æøÓiu-3Iòz.CK¬B|uÏÀ°qhÒáK #÷çº}€VÐ{ FLUlM%ƒU¢ƒŽøOBúW>KûŒKE£Þ%“¡w˜'àV€>½Þבæ|±ÇÝ—‡®†¸ô©õTŠ9²“/Ä«TUûy¼Xø§Mî×bBû†-Ú\qä¿BÁ¼ëävŠM’ÏsƒB çZÁN’¨áK£Õ5”çèÍ1Ì kÈá³F¨¯¹°ƒ1_o • ª½Ã*ZÄßPÐ\íÿ¼n€‘>°xéu0%Žƒ¨'ÕɰãÊ®á!Ê•t˜?ZdšQ ó‹÷‚¥v®»/ŽÏ©„ gÙ©/C¨˜zf¦{,îyšûÜS">ò­"Æ¢¨é–!ýõüä)/ošJTÁ=à^˜Užp«°ßªž4!0ßÛ¸[ѯ»BEô‡ŒË™{úȪàî¶’hªÀ‹ **£S&ŸŒGU‚ ¹‘ˆžª~S¨äCÞÓ›.¥¦AfìünÐ…×£ñ ‘}ΉÔ_É w½Íc-xèÿ±F×Û~§ù±CO;yë »ùƒ r‚'Y83É ìqàÁf¨‰œx!ìÝžkQîTÀe)ÔJ~‰Ž¾»À%©%ì Gušâ,âùô ™Óµ…Æ:æ0nÇ-HbÏgÿãÕuI[ݯ»=¢žÌ꽘;Ã䵚 ‘­¿òý$j©B(èà NyçK™ÏDzï1„y횦.GðeUŒÔþç!ÅÍ Ÿ)Ü/Ö¢²üi…µ¿?æª ßË·b+¤™·Gñ}ø¹%³Š\ ô„â¦gkÉÏ¿1fSjÕÑôëuˆòrúÊ”Ä,NÚ9¹Z ZŠ~Ü`’‡ìÄ0 ²£ì¡Z,,'Ø9ÜŒ$z_#i*¤ãxL!›Á™”ïtCm:´&áBž€È…Ñ>ú è”¶#Í6Љ´Õ5ŠºQHëruÑÔ3DPñÑð‚ô¤>°Ý#ð"…ËöÆ?#<˜‚®¹JüA(ÉÏQ³Hß s·F*«ЦecQ×k¸- Œ`ýZ©!‘ Hæ³~±ýhst¸¸•@s¶ÛAPªC%c_á볊›ì ’L¢õÔy^'E±¯Œf¥îÔJç ~¯^EhãCø&¥¸ÌêãzªÕÐÊ%>áí7œM~7ì¹ ™Åê³1³žkÞè–ÿy©Kaž3JuPu£—hv·Å}¾n*¶f[œÛ]A0•MW ­l̈²ÃþŽŸJì},AôÞwÙÐvÔÒ(ÞÆoÍÜgY$Þx’WÒ!죭ÄñÙ—Ø}uÄnèT·böxèuÇ6ÊåQØCö1'I¯hÇ:[¬™½aÖÙ“üpRÜÙN¸Eöò1)j‘b,áÿ(y¡% _†»€¬ªè( -ýìöíLÈþ@X®p# Š-Z©ïaÛ‘ÃˉA\}†å¢0#M±$¥ìEÛü(&›Ñ›ÝêCÂæ%¡³ËÙ€?B¹¥- Vï_¡‚ J‡¦pªBÅá*ô!ÎYE§œ«þcYx†:~5ñö¹êÉ¿Y}máÙ2À–pâš¿ ­q¡øÈ‰†OÊc"7×äWšc&xÜi-¢À¹×–-Å­SýÀMmè¾_²(‡%´ˆgWlÀÚy‰e‘ŠwOŠÁв¥r1?~¶0Øjf õ$Üš õá ŒX5ZýK}ì¯kˆŸŠGÖÈ.­Ëú­1·ciÄñ &‘̻ʟ„bÍÕB³{nWÍlåˆÒDBÞÔ:™Ò²â¦þ²3ñ]SÚ/¥°(|N+дJG†`~4Cå %,š0Æ~5Aó×\mt¤õé>Y3²Y»º-ò»iûàÓÚuN!TˆRaØ3ššÐ¦²@Ì‘xtÂ’zÙPÉX²o/¦ HPm+Ç" M¿1à.u¤"×w,‡ª_Ðé“C¥Á2Б¤!€îüNiômÆçÖKrfáiÛI—ZºSQú зé“[ØŠo[É2œ'Jdäv[âRtŒ¥wFòý¹g•˜;ÇÄiMðh`§ö4VüÔ‚p‰byA[¥_ØEô /% éØ_qÑ©K‚žEB>ªûñ+"àsÆÅô„$aGªÛõ-ËhÏ ÝÜìNéw‡ÌÌ}¢×¨0“OR+m6ÔW ¹Rs{¹6´Þo#òœš9#ô¿O”Œ‚¯¡á™Yº¥È‡Ê…ûÔnú¸Z\Ý4°G²È¾‚ÖÁSòx-ÇXƒvÒG­“³[§wÊsÔã,HßP¯ oé^ªˆo› ÅÛ+Iw5­ËÇ)ø8Ñ‚´Ž3â ì5 ¢Ÿµ›nƒ‡pmnSg-2žÃ›iú¦×ç¿VÒW¯Cü²lNe'·¬;ðlÀÁúSŒqМGŠo¯;ö:\C‰Ì\³*+gØ“­8.Ï9—è1ׂÙú3†ŽÏ2`ELÝ)q·+|~‚´E(Ê·Îú­2y4Çq×;Ñv0`ã¼½ÔK©l‹bm¡žÅ)0Ó QJÒ2¯~ù'Öñò7ýè|ŽrëÈxò"ӡ˹êbªCžø8å8›D ÿOk]Îë%4Ï#S¸ku‰#x‚T?AÓ% ¬’¿HýÚgÅ‹m\°`f¼ÀÎG£k=Žž$4â+µËyñPÚµÖ®èh!™†_#"¾¥õ$uªõ*½bv[ô¿[w9‚@ÔS;Õ|Ï5ç?IbYWr\Ë'kå'­[?±]Üb—çMê‰S 'å ÐeÌ€ýre´Ü“ÿ‰õn ؘǶù#Ý\cH(ÕʶX«…ó"¶J¿±}Mî^p"ê‡Ð¥¶xlesht–[´}¶¯íι7qÞ©„’µÝ"'c™„{K³´@y>d](¿||#RÑÃzæ›Æˆ ð7óG•ŒCá„¶‹Ùèþ†g{³cÖ_ƒéìóg´<Ìi@ÉãÃðö¥¼v僨N?ËÒ˜[²-h‹µÀ0†Ö-BÝ;üYÒ¸) hc™çÃfO!²6’"Uí¯ü¬¶ÀõöÐ7ô1Ò×Gé îÔuñÖlÑϺOΙ? :/-U˨î™mo“‹TÒÈ¿Ô` àCáÛ%À%C ÊQ•nï~YG(`d^0wœ½Èºêó-IEjºB¡‰aXÁA—ݤ±T)ÖÉ.OžLò‘¡7;.Y¢Ø g‘Ëu¶ŽúC½T/Zv{) îËQžIò)²Ÿ/Ôt™sŦ å«»›Óä‚T© ´Äm´¹5êx6ÿ3VÙáEPá:äÏdñ¨R¥ Â-5cUÔmÎ7eeɳ:£u—¤ y«swO”«‚ÛtìpÓ‡8§µx =1;×KVy¶Úp; Ì%E%«–'DK)à A|.C×µ~ßDãðÓTô¼¦àèa:­ˆñý´‹7Ì&  jù]†èÁ~ïÜKT¸êD ¤ <_Å,4ì÷‡ º®¯)0%È?¿o¼‰Ñ¶L éÙvhf>FOþ >jCmoð@õ×äVJ/ö®£ã¡8Xiwª" ‚!åcZË£b·úŽRŠ Ï–»]ta`fø·ØjîôgÔ¬ð:xÐçNb4T\XyV2¢„cmî°i—س1¼`¯1ã€Í Ð—:ë~ŸèÓ3+´­¢´“èF{¼Fb|£†õži8ÁB´ô[5¢‚äÍØ¤{ 1|h˜Ñ1ñC3KM§¦(0nïN2<ˆY…óq*ÆÓöÁ=dÅ%À DQ03ü<b¢ÿ‹FÆYSÙàItɣޤå05÷¡, ˆzb¶ú¾BîEA³q|é­ŽãÛ {&!Ch¶{··ó•±çeÿ m¨-мrÀ†BlÞÀd©Ó.5Bô eÏb`ŠÃ¾}«/òm¥12¸ÙrüæÎz'Y´) ©Ñ9A1_@Íeºäè½²Pí1ªzÁŠ`-W°,æÌíûºLÔ1Ì"•;[«1­˜s„š«$ÎËÏA¼ÎÙ•~öð|ÁY†yQê6«·±t"¦Ÿg¹L•ä÷TÍ–yt-R›-~‚Œî3Uð„sjç ¸Æ9&W~e<¤ùªF_ GÚÊíˆQ­v^Õl®áûÉÀa07½zæ]zF iRúv.£ß1ÔS>o“+ù ï܆Ü)wµéËLhp^ÛŠ˜éaÒ&|}í÷vúÙú±}`ü͹2@òDPÇ„­£W¯dkyÖ,›e€ž>\ëH€Í‚É@ÞNâneì/”…¼n=òú"Þ÷¦àö;%tP™Øæ€zKöÔ“ÕfJÓÒŽ˜ JÁG¤‘ªôc¥c:MÈOŸßÍDzkzoñ¡½Ù4OJ—ŽØ\¸/Ýþ Á_„”Lìì, èßܶÑÖ“¹¹ }ej Àn™FøÄyR}ã¢8`ðynLcêú%œºÝ§^ýcN~;2Õt£6 … ]}á ×Ö7h–Ög÷¥µ5ö•R‰U͉Á8h>SΧ×EÆ™šã”Eƒ–*½½ €dWE㢰QØ"qÆêÉa$©Ð^]QZlD$¡ÇûÇ™ô°v#}ă¿íd±$4…%š,_‹A¥%Z<ñ,é‡=ÆcÑ…ѵ¦“Ƭ¤Üw^Ð[Pý0Æo"ˆáTîb•uåŒH9´¿%6Äó­øÔ7u®TuTOKwï Á=j†›hº³ñÀ]VBº€^¹ABò!u°iUú.Ü’€{¢bqÏÀÑ|?ÐbÁNädØ•mŽ`㙊¡ L3}G*ØOºë\E.ÞÛ4«8]°ü’}«1÷[ýÉÕ8–üs¿ý‡¼ü“sTb!Ùr/`i”K ²\s0÷%wPD$¹Æ<$7Èšž™¡˜ˆÒUv]e“p¥6-e厃À§˜‹—¢+‹™ æRjìOÜçâd‰ñ¡²Ù–šh0‡½îÔ+ëöRŸ»P´5´õeKA–[WC9&ÒQH¯8h´ÒË-:»2UD¬I9ãsÛ­ºæL1ÞRsÎ/#VM.³¥ˆã3ü^ºX鯲ÝüÌs‡®iGÒÓ: Råq6HC©[EMÇ3ý°@Ý®ª ½õá½ÚßFäƒw¿Pªºô+뽩R¯/×o½FQnãYD´Y6ÁtFLD­Æ¹—Ae¸ÅhÖÝÍG°1ŒXӞ䟰¢L}š”.3èÖQ5 :p¦*}¤e_ðe(§F±X»8D.²<»¿F P8oŸ0×ï­‰šÏcªÎ~-¶ÓèL²Uv¸4OEDß>N0 ªW.ØìâJÚlœÙ7¶ÕRÒ›àøÊˆÓca ž,K¯ÿüÜKDæpÆþ™¯¿d­-H½¹Іöb¤3¶=©V.ÿ.åon|Ó¤&³:ôS¼ÎéSGýâê¹ÌBÑÍ»'Jæåé¹ Õ§óçÓ1¹sõÁ6iú‘çŸk«¤'ç¶ü?ózŒëkíÁiöðU Ö ^9ÎE>€Ê/²û²\ ¢}qÔïÝ¿ˆ+àìÝÆWÛÔÀÇòî}}÷LÐ\þHòõ[K¨¨ŸmÎxîNŵñÒ!£•‡ïV,”6Íô°[‹ð“sCÿ‰vf‡ ÅøI0 yÁg„°ÿ,“Ŧn¢!'ºA±¨åaNeÿ ,¤jx–ÊmLDÙRÀ./‰4‡éí‰k>Þµf,<¨×ꨑ ®¸Lÿ›ƒ`sgYotéÐ꘳ެÞe BÈû­îøÅZTÌ&€ ÿ­\ku"3JÏ­sœ¦ m÷1<‹ ÒÆ÷Eæ5iÖu"•C¡ø’­Üu¦t±^æÁUQêœÈR ¦2yª¯ÿ2þÁÚ#$S nåúM')Kyî8¼LcûæÏšB÷ö®Áª† #b|'¥´¤ð“ÄiÞ'më`•‘4p„6¨ž“z·g¾p®ú]Ëk¢¥ãWg,¬]OÝwò'X†y¨­‚͈¼ AG/Ë@5 ( °ñ5w®V½Ûr®f 8–ç§q©È„ìJõï ®$¬êÙ''0c©P&ø¬U Lþ:M<©?¿p2$ΘR'ÇfV©Ï͵ãD•r"ë“ 0*xQ$噌Am‚UÚ[úç ÑЃ¸Yä}×ñɱÓ]i–Ej£æP- ùÙžõ¸yÐöMT¤S“%%»ÒwK½råeÀŠ~|×KÙ½ƒ{øà-ï'’x¨).sê!n’íêœëgÏ\ö_·lÐÊ4±Ö×Zv{ãå’rEí¢nÏ2®'Êw#¸I·õÅcíHÙ¸OŽw³#£îc0÷Ì"ø1‚›ä7|†ó WD Sƒ¨Í¡úHùÃêyn´ZþµàòùWKÀøuã2o Ü+†û'üì°Î1&8æ·ï8i{ÔÑf>ˆ¯)×ù™í¹4ǽ)y%G½V…Ž7ËDT­†Nòª þ)úsÒƒñ!=ÑÓÅ3u‡ûÍ›…)Ä|ýÌ:–Æx¬¿;ÒÕN'éÚߌ’F å«ý»G R·<°f™7ÀþœLÌ™ÈC›žn®ïžÓö$Ö€/«„bƒÿÀ•­,¢Ai™ƒO=Z•\0õX5ŠÙ.í§‚ƒ¬?êmKUºY:„þ&„5áõ­+1a`åTéNjU˜·Múœ +£áGÍVÙS -v)•ù¡µ<‚Î[lR’¦þè-”´Ó«îYî·9¾d ÏɆÿýn>Q¿fˆÿ½ŸÝÂ[œ&sçM€í$*IôÌe˜?óTYÈ:˜MûU ñ”¥Z±Ä.êD—I‚%,o»†Ðµ'ù…Ú4L™Fªž`wÈ `ß÷&˜O@'I¢”ªo:8˜·â¤In]k'ìÑJ¬ Á§]Õµº@ŠóÔšûü{,–-8Èë´Õ“W9°!o3-¾-&Á¢ï¨¸mñû]ÞAŠ4–nÚtÉ?„Þ¾U¢…•t·¼ ³t£Û[¯±·#XŸ|ºg}áÌpå”y›˜iêwƆ&—²fªFMË:õÇ 5ƒ™|¡ÖO“Ó…ñ¦è™í.ÕPpÁÈóFâ¼)þš=Øf¥Ì,[d(߸º µð.è=v³köÞÏÑ1W;ºò=ÍN³&Ñ€±%yþ¼½{c;©–*øÝ¡ݺ®Õ“œ“m´ôœ_~zèR(KæçÈúV蔞ÌcŽ\)~¶>uFòêmµò1}£šû6(@µ“¦¼\^ÿØ“Šû½¤…ˆÊ¸?4/:ݨ³?L¢ òþ¦Q¿…^“zÚá8Œo#™´Y±„&#êžXžâ$³Àaü5[ßü[éj ßà!û¾“Ãéæ>t:8ï1§9©Þ†7ûwÓºÙ0Jî ÇËãuMjøóT†S‰O°RÂMÞW'Q=iDŽ‚«–N²„êeÏîÄÖ)ªXãpg÷»M¿ÿâ„ãôVl(ÑžS@þ”ÏüÅæ¢:=tÜ´˜ ÝL¬èÐõþ"©ž´\r¾ôÏ•B¸tI}‘Û´?dŸPW·EY$×YFâÞ©²Á2\õMˆÊïº8kú8™Ì9Í6ˆ½EzÍ~ää¨âˆÓJ)=ž¼e°<þnY³ü7–º')ì9µQ5¯È;î¶T°òøß³Ã‚§¿m ë¡ðŠ+K”T±Ç^!ŒU𠘞<ÎV;jûÀ'#öyÇÑ'¤ô‰õ°'æýêî¡Ázp=,*Déñ¶_ãÊ-ˆµÎ4cº“óâ7’!˜m$,/i÷=@««¯ŠçðáÔ {DM8üÚÌRÅEöÀé¼¼wb|ËGÿSBõ¥ðœÇù{X m°'’ÏÏ•ƒ¨Išˆ¨ƒH˜–›Ð@zázcTEéŠ9ÓBUXàhc‹]`ƒ8™<ΤÿÜQž¬Ø;s¯ý9q|ü£"6ØD×,`$rð=#ýK2›öY+°QœæÒ@`mÕÄ ÝZ’”œ ø¾\ì©a© Ÿ-m/f˜·™Nh›$ÒžæõMŒ[°êXz®ò´ ³¦‹ÛÂme·â³~óÞ›ßP½öÃÕ>ÉS.ÌãÕâ›i:‹pdÌ<› -þOh{VÚô£ÇFQ?@…h!&Ï=ªØ”)n"zb 1aí`åÓ0ã´:Éd%ȤG%cU!SŽ— {˶”Ì=1åÉäí;:,érˆ4+©¿S³Í0hú”ë!yÀO9ÑÎÓ~Zà v‚D*gSc \ÎÖú$"«»BBa%ÜFà3¤SÕ>„®zÒ¹ÚO¥vëÁðÊûh0;:xz Fà÷ÌÃiü4Ýhþ15¹f^á*–ôÅK¥Ig;£ý/M}ßhIq£¶¨yÌ æ—tBÃ;ˆû¸òã®xkŠ&àÈ›4Þ4|ÿöE½"OõœÅ³LAäÙ¯L7ø¸wª>P™£³÷Ûšö·o40 ƒŽ¡G7¢çŽGyŠÄ„ö%…B¯©á·ã µJ…_ Ÿ¼vAÖ0·Sfù­°Â0ܺži¯%M¾–¥L(@Ǽ@ewR²Ù7›©¼lõ…!  s+~›Îÿ˜ïhM¹çèú‚O××amñx N|Jº–ðøÐtŒb:IBÑŽ ´Ó$§3÷B½0`ÄCŸX› w8,ÕÐx •àpâ*Z~÷&$;gîäË9¼é°tQ0f*o÷¬ý£BCCŸa^,‚>ÛÝjœ2ò5ëÅ4H1\c¢6º·þÃñ>e«ÚЕôQP‚Qr¦o*ǰÁóRÛÅÚ ¢¦*†¶´P+’2çñòŠmóð›ÈáÐë£mg$Ê=9¸š“ù´Zö¡¯v³ö¢±X~†žºþ9°;–;éß I€ê  ð-ãZ™œ G£ÃYDÁW‚HœÈÂ^Û· ¬‘H.K(­ÑAˆÊ"ò¬¥NLæñ瞘ٶàÍ„#Ø·Àt;°nLv{š°ôˆ«ÄW‘j¥{¶=g E£ÁH!ƒY†Ü.ã?“zÅ£-ømš zm¾Ä)Ñà8ôk ¾ÊÇ’Pÿ1Å0Cù0ZEµ0uÙ{áµsì19‰<ðþ¡\,VÓÞße"ŹæÈåké‚Viq êåá ”8qi¹„Ï¢CmÞD.÷éäš×4=¶ö™íî ¹I›ía%HòC‰o'¾îãê-6eÌ¢øW[ðbê˜P4ç©þ;6VÀ‰ESQ(o‹éIZ}m0æÔYG•¹ÔÊ— ûQÀ8:ª˜Ã0ú‰ÈoÏ‘z=þ[R])WH€ªÿA²–Þâ íi#a$ý@£è/ÅÎÒñ³¢!îïh«|>̧îŸXÔœø1VríÈŒöÄtj±èió¿„s¯É g F¯(b+0Š'0ÔÒÝF¢×À‡'Xµ¢­_ŠÆ7Ko¹½‡«“ô²{t¾÷ìÕ @‰´JûBééüb½²!ÑsmûÝ/€‘Ê?/“Ÿh”Þ‰5˜õ’úÌ~3, ycõ»N5¢ù}oo2_å„›áçe¦—±Päç7`ËØÚzµZØD-bí†à8ëÈ êUB‹§©”w2j¾Uìk•FÇŽúy°R3ÐÃ\‹ìȨº¥uº±SÐ…«­ÇÝiêTÂ_“›°<¬’)ý“$B•^uÖœ>éli!«c¶™Ö.q5øA€¼–§‹÷ãúê, &÷zb8u´ šÝç°¹õ6ia‰î3l¦•°ÙN¬=çAbdr³H 2ùv-£[7»û’|ÔEu{uøì3£‘–F&ïŸ[âNØo»É0çuV£c‡Ï|šßŒèì©pCµèáÏõÍØb©ßHÈq,Ú„YÙäd“È??î¯øe¥Qöª«ˆvóˆö%0ü"öìôâ¼ “6NtÑdAÓbf0Š·!úQ½’»¬ÛBÂ;;ûgyòFð‡µ+ÏähšË·éœd/W3‰Npƒ°Á”§ÿü‘ô`†½Œ!Æ¡Íéi)­9“ÅýpЬtpí¯!´Û–©=çWÈÊà\ÔÚ;½ŽX[miåNÓ¸§]2êá® ç…ÅÈôx q™g “B{ÿ«ŠÔ3äUG(%DÛ,‚†sdúwªŽ| ç²9‡—ÐÄ/#AÕC—©‰+-â_ë Æj!€VyMpnVÈ»,м¢öÙ(„ŸÂ–„zSÆi*±ƒA×Ç@µ±á{è%Rú:fhÙt¿êÖ¯¼šÞh¿ÄðãdüŒ^‡ƒ‹hý€¢éÇe•úI`UqssÅÞšêà¬ÑÄ‹ïÌCøj-] œúrh¼.¤ÝO."¨2˜‡¾@òz¦èÅxôü†Í¼~–~¢{ÂóÚP`ëM†ºêË÷n 0Y•Ä›§œ.Δ|bÃF…¥”vì5h®LÊó³£ì~"RÒ× qk~c¼›¡¹ò¢Wa]ákä|ãr °=úœ>Æz}_íþA­CYЫÙ_ Øp ¡ Yª"nõ „d¹U ÒhZ®i"™sÏZ´2#ÃðTëKPt§ÄãIY˜0.À2ïÊ Ã5…†`vÍeDJŸ¿RgÕû `BEw€¼¨c[¿ ¤â7äŸ8³&´õ5ÕUŽÎ$ÀÏç³Ì0ƒQRû§TÏUú gÐû;_¶‰Óß]ü¼æ*Í\…_é5ª|l_õÈ£¢¨;BS~Ù~TJÉVŒTLåîI¤+pŒÎ@‰× )­9íþ¢Ž”¹UÍÆ4³{±n‚g•æ@!ŒÖ ñ9y’ ¯|KLô…?iÂõ…åj­Å'‹4äI÷b7o¦º"¡:è¨2mËcc§³R,Í“ãÈŽ'bl¦ÏL‘ÙNË×XZ7zÓoêiÿ._š&Ò§K$1Öøáöô|HÝw7Úq2JÖÏSÄ2¬EÒ®Åè Sñ‡w–óËÞÙ”ø‹ACº’®ÏìE3Ùä‰Py5ľõxÐXä›ÏþÁxÄNE UâáÄ÷‚¼c‘Bæ&_‰u׳{áχÙÔÝ=mM*;=ùs”£Ÿ¿Ó÷j™”ª¾=4‹0…¶¥L¢/1/`-ܯ!žÑ³`Á+¢à æÏ1]Cïeb^Ù¯bˆúQá^Ö=Âðàš}uwZwвFr‡œÙĈ"‡Í²qvàÈ:PåZ- =Èæ‘Õ0¢·«Á]˜…N¦_cðs˜0³’å:ÀõúðŒÅTZnûœGW…ie7³½i93F9­z؈¹l9ØåOâ}6ôÆö$2õ_¶xÇ–"3hMÀ´ÏíÖ×-uêªwë=9‡Ú$T}‘ X… «;Å&W®R.þœøÛÅ8…èÓd’PéܨÈÿΔ“&’¡ ³n“_!ímFÛ¼GšYŸy@Œ!¾-ÏÞd þô0ô‘r¿CRÌfâ÷ž^÷ØÀ‚T¹çˆ1âðÙ%ð ˜ûYÙÆl üç€À~ñZd÷£eDRÕÌûé>• 6b’ô*ÏŒíjo&g®æa$]«$éŒ}±3 2UcoŒäòcB£³ÕU7&.êñ4‰:ôà–¬H®¯<ƒÅ®ùvcK•p¨-6‡Ú¹¹Ý2lázÂS4=u&‡)rk²5ÄÐny«Ô©M˜Ž‘±œåÁ q„`l´Ç5(Mtïz[FMÿùWóná É[ý«¼ÓUý”‹·ï R 6tþ ß ])é“‚$hB/‹UâUËÔÿ&@Ù¿wqr"‡Ü¹á•/Ù·¹òç#JSy-EÃUïGÁ– ";”ó{ÞYذþ½ &ffFA+ã§Éá‘Ã[F*¶¼/Ÿµ8ÓÜ1ñù†ÀŽƒbjã.·uuLFý£Qô%HˆU…'…’ íY褛RuÊäö ¶´®ù¦ñ)AþQÚÿšèîv‰»|“\Dp'tždì) À±šP]Š5©©¤Ú_ Ú®0œW8=%ûÆD‰0OiL,kÌ–§Úª>)éšwXDÜ&š$6÷‹OLòm×¼OM½¼ãÌÕH¹ÓŒPv†+ÿ(ñKÓ Kþ=ÒüŠՕ€’ bÒ»=ÃS2ßþ„…¯6ø5õÛùÖ™ÄsbPùžq1Ú&húíÜÃðô @¯ògüên´Ì5b{ðÙÄåP`´˜£Wƒìõop)/ò”JY ÓšÂ4g=;Sù±Èþ•×OÿO=‘ÇBÌ‚Ûz A o!D9¼`<ØÙ¦½fR)ðr¤ôeÊàŽØíK?ÆïÊ6\¶/×3÷”^ ðÊ)zB¶*ß5íè=Wܻ޿že?w䯻fCAš»ör¯P*U-ðÉ¢¾=×!SA¾€@A&ùÛãpEgú`Ó÷ äYþK(5ŽzšuÙxoµ)L‚”­Z[=CxŸ0–šæ•ò<\Ž?jæ¡+õè?íC±"áÓÙhá6/»À^Y[í×´™¤’²R•géáÓz÷ìß¾¯á„ŽÞ[*hç_ˆºÅùÀ°9€¶Þ]ÂŒ?hc§@víåÅ7 ë5T¥¬L¯õÏT‰Žˆ>0³ÓœEro>¥$0êZ~Æ÷Êirî²eÛ•YàvšN­ 0Ø;_ þÉøÊvøhIû t:P) ã¼Ee:ä_oGÒŸÊBÖþÆj’´à©’âQQ´‹ ÌB˜ÖŸÚ@›£±xæöþnõóZjzcv¯Mdh4Êj|ç¯M¼éÏw ‰¾ç;ñ¯Uc2fÀ‰ÉñÌ–æ\Dw¯gX hØš÷4ÒΓž©M:É·å!syÛANó9D¤ ÎÈróÝ7îÂÍ[«¶†ÙhðݱXnržÂ N–ÝöÓ¶Q“¡m¯t¯ÓzD-ŽGsÞ\ŠÍAÖ®é{£äÅh4GvÖ–oñÕô¦9âž²ݘ֔‰Êí0ŒDAsÙl”“ aÐå_H²Åq*FWÓÐv@÷_e;Ÿ5*ð/õLeÏ®[òr>g”ãc:[.ÂC¸ÍŰE˜ˆŒ[íA‡Çù)üŒG•â#©,y²Œ†¥±ýwÌä-•Y.#%ÁR¦þ[}¤¢c;W"tÔŽµHgÖt†,fKÞÅПA­Š­ã|Ã<ÿ€1üáøðåÈ—²?ýº‘AiDûz)cX`-ÄÖÂ<{’ÚçÁ/+ζþ\¹Í®ù×P}q3M¦åDç°W¤zÈå·¹q.$ݲŸ%€fUÙ>½¯@üfm‚[4½Õ¬#øóþ³#“Ò)¶óåÓdr*¹'óÓ+yv©ÕÁª2óú ¿äâÏt½–¢ýYsÍŒõY¹†he˜sê_Ò0ø¾É¹€É€ÝμA\¯Ü¶ˆùê®2A°‘+~ŸaüQB'zNïªË–5›fc™1ÃyAÝ÷Þ r­­÷§U/Dók&ý§¿ê0»\É›ƒ>í¨¥ËÛù 7ø#P0‘¯H%]CÙu'kÖ‹SK+6ù’BRR}:¦w)Æö7Þœ ¿’(ÁÓ¯½ v[0}Ü>¤‘‡þrù’vd›Eõ£Ä  H \±`£É°9W_<1ÐKc¥o@µ¹î=lµÁC‚ùpSèKß°iSAĆv4,n¢Øüy‰îoÍþ÷%L™XMI¡ñjh$CI³Ã/9˲µ;ß{ÈY„å˜ÉÃNPÇÒS³”U/ë{= r9TKdw  ®;Ì¢-³ ßŸ­ ß£àö˜=Sœ|Û{´”¯è::Nn‘Ïî>*¢S .¼ÛÛ½ü¶åZ°•½½M'OÔ)y âAAgU /—ËŠAsñÐÚÕMÃR„6èF(šFÍ8=øôF³ÍœBkzB÷ï²b6˜aßáh>,»øÜUãæÌÀ_¬]7ÇŸÚÓ…g#gÔþõ–Kž"óPmf+zä|yÖk d:Õ{ <²«›€ß?‹DÊ|5ªÒ=Nd«ËËE,OjvÒc¹‚Úþ<¯e€Ðµ#‹ŒËR!—1²¢÷3Ñ>+¬ÙA‘–ãd:«I×àõ£ž&¦'Φ„™óë´PÄXŸ{c€YÔ ºiÌûL\ä’{½ñ.|•pVÞßóŸ8Ká AD¶9rôgU—w½&µÀæðI™èW{ÓI\%ôIÅs(‚§ƒ9½é& V°}ßiÏA.Zû¢Nï45X˜Œ¬áð Ú£°’Z¬ ÷×@W}`–ãÐA»ÔÉBà«ÝSä‰@ )9‡± >KÕäÄ›ÒùA¦ap “|SsõÂqyœ‰‰2®>¡dìÎî}¤p¥À<ÿj‹#9qÓòªXÚ7íé ø{u|QnÎ4”aº==¯g2h] {D0p=¨Zì¼}”ÀÈåT•ûŒd< 9¬V|œÔâEØ“¤åašÚõ—' ìÝ|i/t8Qšªî÷?ß;_Îbç ¾½ˆ:2GÀ‹9¥>±P~^¡ÀºâÔ³ë(RVK<¢‡Õnb·ÐH¯çTÿ‚G§w¹¶ü`ÀÊÇÆuªuEʹcU‚©*Ïû74Á[C\ŸhìÊ1"sR)¡=þh@HÉÏ‹œ¶êÀ ZWѯ”kÁÂÃ^$‡ã ~ëëö—}ú4LÎÔÖ§¡ƒ;‰D$éczã4ÕÂà U'íñ ±$6“>ôÇPCz–`Œ»ØéÞR›)Á"r¤x¿]¦K¹¼Ëm¶6j †Å¢¡M\/b}ô<Ñ;¹´Òf—ýn·Oüi?ó:B¦S‰ÛßÅp®&Ų’/¼—7IVÕº@çÈ(S9qèâ=.¿5þ®ãFF;Ü&Y–JOKøWnV¥bh4œÅ¢|3EWÊNq-˜¾Þy³\vÿÐÀ/ó¨uðŠÁ™ú|7  ¯ìñ¡þõ¡ P­¾2ä&ÕED6XÉ9º—аB¤cìN„¹Î °;¤á G¬¯»’¤9œ'1Ð p÷tĉ>¡ßòevƒ/¼¤"œ9AJ#ã/Æ&F@! NÙ¤Ò éãœs<ûG¼õYt+õ7_qçäNÄ 7!9˜Ë)ŒU"ÚÏ&ÚÅ£$Z]¢2Zöq)åéÆqròŸÃþœAµÞ¬m eEÄ7>ÖÂ/€`÷ŒE04*ŒväRö> î„IÉ5é´Ðu…²Ž³Í²ã!õ}ŒÍ¸W\eÞ˪В IÛ½ ÷þ@ ê¼ASÌ^§ÅSŸ>1J$Û¿2™É\-PŠÞ¤×/¢¯Ž‰W„•J.ÑQ5H‰À Ï\ Ð83”óÆ>\ÊQ²d¢à-ÞöÅÇz€íu :"¹mñM 0ÉÚÿ%m¾x:.úÈÄe•Cý5ÌgÔu.=»G¿ví)i­QéóÊÀ«‰;š‡£Œ´A óJ“Å$ ¶žUÅæ(üÒSê8 —ϼÕq¡h Éá3µß‰J˜;4>RS€í6ݬïBR(coÔ¥-”Úå¤ÚF [Ÿ5 ï%‹RG‚éãÀ õÛÊ~ozr¢™EŽìEòœ*ñ•ÛÉ#uñHºÚt¿­šï%{ƒ6´Âƒ… 4ÇãHL\WHªÒ”•ü³`šÍéÚ·ÀzŸSæÿŒqÚ|~:NñÐ$ m€"ä£=^`„Ôaéh_ä耫ù-}J¸…‹tˆ«QÊú²‹Dû|/¬Éž9¸€ x2°ÎÕæçÒkG Ô£¾æB‰¹+ *eøÊø¸ä™^ëà1RýeýªD–GßKmyp<¢ê›«~d4]¨´XK ù&âV@⯞#ŽËû,PNñm+þÅò(@±¿jMŠˆÃ1x øQÖ•Ä+E21ðM•» |…Ðá\€¾ØçføñÈàVÀÂÞZ%`/>à²tÏó;V¼·#,WE|kÃ˰D zâŒÆŒ|IºÈ}¸O²ÉIÿ×Sì-'p©è=û|!üéÊCª©§uÔÉÈöGr2­‹ûÚ¯/_­^òQ\ ©6,­"n‚†› kwµ™ØÆFBÓ%¨&ä¡Ót[Œ­c(ŽWgÖgÆÄd铸åo&ߦŠløÛB‰X¬ ë @±€UÑYE²àØ-4[:Ž}ŒËA*%ž—°ëþÌÁBÒ˜öî2,!*8® ~RÅ9QN›õHO©¥§¼#asPßÇ_DªÌŠïï_ô*0ŠÔíò÷€g>È­ÏbéÓÜo:¡ž„Æì‚Ñû/. #ˆ:©®‘L¢äeÒTp{û†r‰và&•9IŠkxã± ,"éAÍ€B³v+OÊYZtqX·Ê5&M‰¿][ì!_Ö˜¶($fM¡uŠ|{ÕtœÛë¨û>TÛ.µ)µqQ#ëù Ãw+EŽáK M{&>N²\™’ž0…d[€¢2}ü¢½àV”¡ÇÓË?â”L:Ðæf­€4¢ÖÇ<¸ OÈL …=jé†&¯ÛVƒ³©ŠaÈr€Xð8=XH* ÉŒ”-˜†¾«¾4T9%§–ÕŒâÌÔ(^Q2àž‚ÊÁ‰Ž—CX,—pÙFôK—ŽPË‹ðÆ)̳üaE¿µÌèíŸmÏ.¥Ãð~“‘)¦€.èì´Õ?£cœ|ÖŠËÕ¶àZÅ€S»d*îÑ©-»exó)ls?ÇHš ‡ß”C¦Ÿ‚±Á9¥hUhí…'CP–06§ úËcˆC£¢Šš¶ê¨€A>®áyypýNrήpËëĶދêßpßÐê]Ó,æ:IzÚÞKýœ,ñÖs¨×+¾iD‘·7'´ž+ âÃqWBز.r¤}1eGAða¼ˆ Eƒ'd²ø^¼ áT{”s“²—½'t2ŠÚkDR)³_@ÎE›W,—éoùË^©ÕKô–œ~¨ýÅÙae…l™¢¦€ü‰¸a ò·J´¢-^ûø%äâ³\XÅ×3϶š\Þ2?¹ ™ ([»* wVÇÖÆ@g(¡ÊÒUÓ.ÂmâPÁ8²ÉMò–Ñÿå;’e´äC’F:¸ãaJúòNü¼b¸Ýð–d²•ù`‰ÛåÚ"Ò6=êÆ'¯Ð¸ásÅÚ¶J=ºk §Û0­åõS+.úYb¯·|}m\®&bìCi}Ö­Râã)˜•[Û Óýìõýil›—2±ö®v*È~bÖ™iÓ^\°,\,ÃTïNFsy¤Ñn€|ød‹cã´ÛxL#¢™œ]Š/ñ‹‘ ˜„Ä{¯9S­ðN¤L%F6&dÑñ’÷£°Àlä6Ë>›¹ã‹Ÿ*N !Íe%ñýñDcÃ,Ç¿º§X’Æ…ØÖbtŠfr[°¤IÓ0a0÷÷K”w/õ,׫êËÁ¢•½»}Ú§£«¤hú9°“à•PÃr……îïwZn0>i_"®@lV¾=4fP8…aIÍa;¾—ô4ó : ÐäFþ+™ 8î6Æ[þ ¨6½&“e5è„Ñ´}àÁ<§cÍñr¸6FŽU4Èy BÓ«£k÷ÆMxÚ³ÔfwÞå¯ÄæNE0—‰¼ëÚ„Ô®ê% çåûN‰R¡„®É:­)*x4á}é`8)ï7anѼ_•õ.#C¸aEÃ.ý ¡ÖüæŒÛøù“)—ðù4¨"ãy%®ÆÌCòlmý!ê×{=/¡ÈÏ7I@ö ê|胆šDxþÈ›9bLþvüG(˜óD;dþY.®•zMÙqegœÑvºÆ®{8éø`f“²``Æé<®Ié±§•óŸ=„žþ*¯k§^‹òo(Îm!¨9X?ŸÍõÌ3`ÒØLåûºF7|%¦"LÛ¯ƒHyCpQ~9mÛÓ[QáÅJ7§[¹Þ¨`~Œì$Šmõ î¨¸e¤æÎŒÁ­Q¬ÝÎmÓ&Vn˜ü^‘;›£ k,òí-Ò0 «ÄýbÔ1§R}>ô­,•1Å“ƒµØòõ2~Àæ½D^ö”d¼…Óí!جnsMèɳŽõuÂkf™Œ VÛ8/³GÊgÓÕ«ËpbH‡cý°y9Äln=ûQW(/ç's&_½X5."|CÝBNV§ ä^ÝÓ¿_T-¼&LaŒˆ×R¦D? ùÿ[\>C¬aq)esðŠÝ‰~íGønU[Hªl„Þ 4º3ÿ/GÜE˜:Jm€h¦Ã^.Ò£gp}îé-øLõ–|qlMâ ÙIÄnCäù{¿.@#PØLN Ïâ;’ ¦YäGõ:¥´[U@GQ=ãFSió/sÝÜ¡Th¶½ºcœ:`@E (·ZÕ~`bqìhìßU¿(·F¨ú¬¬P´ÎŒÙÚâÖÇáòFÌßIÞBŠXø×£3…`QVXv®/Xä«áDg¯ñCU„^0,ÌeÃÞ_®3ÑÎÇ’Tòá‹Áª=‚Eêtòá'ׯûzÆó|åsm‡nƒju$ <úþÊÁeªKV_tÁp7_3hQ‡‘—Õì „À¾q€·ËðšAâ9”ëOŸæ$¿jpïÀûòŒØý:®QôØGÎTöùÜÏ^Ñþ_®"£åwVˆ,‘å3®¨;hiû>˜ |–¢¤sœN;”Cù3«sY‰ÙÀ\øì¢²†t ³¬“ ŒÉì/ÃR™ÃD×1x$’ïP¨3OæMUhG¼Œ8¾%§V9d–§Ô,ÑJ IˆÚ#ì FÄ[xã²4ºÃ7Ž4ó Fœ¦*¸0˜•ª?l›ñoíЙ šæ¤„”О(s'iVßkŒz¥Å*ãkµu$öØàÄbÓß½DåÓ6³QÂh[¬ eêÒ®«×ñýS“ãìJ+¿…Yæ 0 ¢ÞöFÞìM]>ª¨<Õ™Šœ‹= hù³”üÞF¼¿Ùê¡«Y ~FïUeQ÷>Ò‡2ËÝ›.v0 lÉpŽìïj{d‡r½ä©…`p¹Ru).$kÃØŸŒeÏ­•¢IUîÎ6o47l7œ:j›L=0Š.,Ô]ß.¶ð¬"¤B[œ|wÛ60–…kähnÇÏb&£v!T÷àyTueÆÎS_0“ûÖŽG¶ E®µIÂãACc²9`r‡%ŒÔO /õ‘šÈ6“@­A™M‡fˆZÛ`_ÿOö+Ú²=}7¤.q2®¢檑*ÃlÑ_ËÉ\waW²dI™\ 7ò _‡ûÑ'^ðQÔeÈ×G±‘úaUŽÃY€¿ÔIŠp±œ™ôÎoùÙ%gS¡1Ñ0ð?ˆÖÝ}.®ÜU—oÝ_HJB¢)íIÙå¼M¸QgN…·XPïjÞÔócµ²öœÓV¼(SG{£R«è·lüÜÐÌÙÉÖÛ’ò2nkõK…¸¯m¶v¤wÛûÞÆ¦½nFt¯FÕÒ„áÑÁ 6W $]©ÇKÀ§4$G¹Ÿˆ#Š+EѦT×wçØ±ë¯°ì›úb•pùbAï C÷FÞ›'}3$”6~q”­®øØÃÅø^ñgSsø8Ñifõ™ÌCíŒ3:Ç0› ìû4õ ]û¯ýeü{“q@•ߢG°¿X§íËZðnàÍ—¼·Ä§#È×úÒ‹ð´#D£ìŒ8¢þÛe•.ZOÈxç¤ØÒ·,LæŒ"QžÝÓ »¯õ“ÓÃRD„×e`§è3s÷Œe¥…¥ˆ’>œÈKxêËf Kí`Îz†ÏÚJ¯–0+ÎÜ÷¬MÊ=xÕªÑ_«ŸÊ^_IP¢7E ð°Á… uWíÃþè%±–r^â·Ùæ X$¡ûswá£è)„ ÅóRßû“@#ó'K¢°“l?þ¬­ºpc†¯´.¡¼ê÷o@ÓŒHð+9ôä³ÙB7$? ßš‡ˆ}\ö€.Û5ž:“7ïÏÊÁãF~âWb¤ç}ì1¦Âõ}w3*–ªQ`tê¾'¹ymXeæ†\‰G•ÉŸQÚÔ+d¡‹ø»ÂÇ^Û­Q?‰¢wbº¢wÞ¯|QËfŸ xæÈÏã²nªih–¤Ãî%¥Ó;Çô˜vïX]e™O×ò›Ó#†ühâÉ—Œ$ ?• T—9¦±rB”Ýå­‘áwšYÁ†j¢¡Ë«;¼[[ëRù–VòQ‹¨¾w{Áˆå»zž½AV‡Id·«sc±<É!Å”µ§ºcÔ #Å1èmnÂh[Ž¿¥•)6PKVùyQ ©{GÞ•cï‹ìéµFÕªÉ>°°ZŸ¤ƒ¬#Ì3Q QŽÃìÂ]û’£Ôá 3Ætüy°ãµ/|Ž’˜–PÞÒ}+uÙDÐí°9åpjò¾öÏ5|º¦¸”Ú®¤‘íªœb¢¼ EE³ÜП˜³ÞÕà¯.^@÷pÏ R6èþâ@\{µ rcú¸l˜ª±ØÜ²_ØLvÑÒe3÷’¯œß´H$x/÷“e©– ²uI…ÑIšø»YcNúÜ«¾{0ÎO˜rôûì&»ÑÉ%ñF 7G¸¼g@Ý¡û[åŸ/š@Ö{qÊ|×›bÅjUàåâ|·‚x¹©Þ®{W»¶M‚ÅsNt³½ÑõýæK“ÄžëMNÖ‘¡úJüSõWnÚëT¼ä¯õN ˆe/G%¶Œãx&8vò|ÉńάâÂvMª‹¡á‰>M ‘Ï}Á·±yÆë© ã9§˜Z9#"®`âÇ‚jÀw&F¨»v¸Ã3¶Í2'GLf=Ežpx‡A^c­=íÔ’©y›#µFÏ`Oã‹dÔDP‰®˜¤ÈJ{YrH˜âuëÙìd¡Ø>¤°¯,j¡*2F¹µên?ú|ÔJÜd·¾%½KÎõMŽœô?#üLò©YFé²µ8yÿõ±óâãÌá]×Ó°Ät_×M—÷ë¡s=-"2£d‹®± ÍPΨ€¿4Ñ $û[CÖsE0‚z‘ GõyÅZZÔ¨OMŽEùÿá zyßë§F6û N!| oÂà(ÝÙ¤øyú RˆÜNMg(MÐööQì_Ý µ¯³<ä †Þöç:½AÆ)U±ß<º¹cÔ»i¯‹N…{ªj}¤Ì+[=CBïÅtçó.֙ܵI§~dS^òP+Âú0Š€,¦ƒ±# Pˆ¶%Š'çl˜ÜìŸì´§¼ßLjټ³è†¬î±ÎòÝÀÞJ‘j¤ ÏY+¿÷LÎ^t¬2Ùbe Ðù |ã†&ð©X±K³×‚8X%Vp§”òÇD^äòÛ ˜\a¶i™ÄÓ§°¼ÒJ)p/ ¢²ñýrT.ãJ9UÄytÃó¥RjìÑ %N[{¶7cÂæÝÁ°Ôæ\·ý‘UŒç~ÑŠqŸt„2EA¥8Œlh&=3H(ŒwIÔÊ{ñÐB"dQU÷i)þ‚¥~GᲬò9q­yókx”ú©p.[äéT‰ØashFNð«lV%ÏÒxÕ3 ¦Å³.\ò²4-‹u[$A¦H£E6~ÎiîÞ% ÅŒ›1}Ž\J¡T-.ß“#zr½ÃÞ_a wFàæØí¶¾ÒLêTò¯Íi°Õp”í,CV›UµÓì´ðÒ¦_æ   –RiA%kÈŸosÖÛç8(\Ä®ÃtPÉÉò{–€þ IÂZQšó( !Ëç‡,E>¨\{éUI‡¤Ô»Ü+öÁk–^ªwLçr#eV¾î¾½Òp‹%ð?̽úNI^ }cRkŠ'.ïáê;æð¾$‚ìÙ5ÛžtÂéN‹YÔ}Tç.Eö“ŠþõÐÐ'ZÇAĽ¾Pý9 $ªÒ <½iWìeƒK§„ë²R‰Ø«&®åÞd wÍòwíÜDå›êÛÚU.üí=5æOÔÊBžFb@YùùM†ÇþÎñ¤¨9{¾¾q:ûŸø"qW}p% Þ’ýΛ¿Ç9ÀµyÁÅ—ËÃ÷ÛŽZ5[Û¥Ý`ävÄ»òkmp°I”þ2äà2GÚC‰9¯yw8ŠcãÀÆ2yÅ3Vœ*[âaD^üY¾÷NQçð¯r™ý„~£ØÜ*öö¬ê 'kÙÄø‰Ž‡ÖŒ ŒœóÕG‰Ø×¥E¤­tÅj 8qnŽ +Y5ƒè'›†­¨3+b.³[flµ7¯œÉQRÔoa”¢wßÿ•{#þ§%ÝÄS¡ÀNši 5nRÕj߸ßÌ`œ=bÞDtŽÑ¢àèä`§q¹ƒrDŸÜ c…³À*¤T“¨CcïpxãotÐ0(w&S…›gÄGAÐsQŒÛhæ3¯/'o x‹—É=µvg?)óÕ¨Cˆ u˜_O°Ïq/Ž‚Ò:¾Ú:7O:ÁZšÑŸ9Ïh§ïœ*ÌÄçÛü¬òÐÃtN“xšüO‹‰#žb÷<Œfñùˆ[Duë\0JÉÎÑÍ^8³{$ˆ9ÜúÕ9Ë¡«©=ªª’¾· 󒺦«èwÄUöfCÁ|໵D}ÀÜ`sˆ®1—˜Y¬¼%1$ó2aȺÊ×+çÇÆµº°/x˦ j^¹/X;'Wi p±%=EÁMþàУöíÌu¯iNvV’±‚ß¼:=ƒ<ú!˜PiNâÍÌl `6±Rnz™‰)aaÓàóüG¥ß°Éü8Ô6ÒZ6x£«dƒÚ¦90wˉ÷ùk“èÅ-G¾d’4ðçÍ=BQ X< £¬!|­vî.ëNÆm1JšJÿHGJzuÏ¢;JÄœvIBS U)Jáÿÿñax¯›ˆ—'r®mè½—6u(NEÅJhT$.(˜Ý(hzå<ËHC1¢Ì-Ÿ¥Q@(»UݹL,žÍ}5 Õì¹…‡‡GC$¾0ZØfC综ï0›ä·TÇì ¯ðF‡B~ ]ÖžòR oœµy/îZ‰@‹ÑáLé:mé;DžJʉã][ô¨6³ ìì ƒ¦*Q—ët+ptqH{3ó<£Ÿ uÈÑ%wYƒt•Ù†"Úu÷±ÐP“0i¼µÏ› A°‰g:\ Ò’Þœœh'VL¢„Ð>t¡<8#[#AïÙÇdɉÌ/dM3ÃOR€ÈúÍ9å £ï"šû.»À*bæ*Å£o¨Ùœª½¥lÒ¼J]Ý&,.±†¬K»]ÁEs„.m¨Pñû HÔºÙ?{~‡sÌ3Í<étAW#Z‘=¡µ#/ …¡' :Z{ÆíõŸW>~æiqÅ8ùÖ„ÙÏ‘°Ú?{( p+ôÙqã‡wV[ÕáÂáëG”¬Ø#ÊŠÈ$¬¹Û.w2²›¶ñžUý·8©H!ÂMƒ‚$ç EД_ÀäüW3ñO´œÞ|íåÅS–e¬»#%LÃ%ôIx+Û΃٫¼57ιôŠS(Ò ióUEE,¢ÄJÿ›m½y…ÖNó`Èð‘ úˆ(ï ÷K¨u»º#Ô‰ËrÇ*dÖ¶½ˆíí‹Û ø‡Ð°¬ðɦ'i½+bu =ÌÊIpOø[OèÜÜÄç%}j­;<ãà€â‚FkdŽšF‰ÁÞ….kП3è´r‹çt´¸sœò¡´ƒ¼™´Æ´9½ÒžÎuç˜kü‰ÅÕ.Há€- êß±^0N½Ä@[¨º…žƒ'¦Ž¢¯'±Â"ž­tiÇ!ÆÑ(ùÈx„áöÿ&Ù¥ÑÓÆ)NÖr°À=ø’»ZöjBKŠ9±°¡o6yïzO®–#ÙôzËÿä q¨Q³ ‚–‹gîªOˆ&dµb®Ý—ØÜÚn‹ªñšü\kгÂuø‹´QHé?0‹Ñ†Vt¸sìvØ4”k ©E\h¼ Ù¥Ü6:Å_yK•b,ù³·LèÆÝÆŠ&‹–?í˜ÑŒëêý\4ãh° £ÈgU1®ˆ„ ªtÖ5_:÷ê,Îìq›ÿv)¢/'FuÔû$âå­(®‚¬k _zt²dv>²7²s{~b²ýr"Í”lª–n¾6R ŸÎ¬C Tª±Ã&hU/1Ù±ƒåÖ«¢_¶ Ë 479Ø8§è¯‹xîê5:°‚/N·Rœ‘/Üx_Î ¥ R^ÍlºC}Òª:>kÍc½ÝrR~–ùL»UWµÇË›^z@re™† ¬·y1›lú<ïÀM$Ýb ,]œ]¡6¼ƨ©¨öá¨ö„s×›®’…†Íl‡3—b†ÔÚþ˜x¢—Ìî&ª½&ë-ÛIÛ5 ϱæ~YêWT=·|(Ö—7V4ñ­}„ÐõÓp\Sò½e%U,Jð?J¦ëµ$ñÓ]Ó³ –˜Yùñnhº~ùNþwÁÛ:kíW¾,˜kkWY#{›»:Y÷Ñ~ÀLkáVº³^¤Î¯Œúoˆý.å½uÌI¡|«pêómé<<3ìèð²5ù›oõ¸þHóàx;Þ#¦«nñiÔ$ðaAhCžü.é\=FÌÑ»È@" —¡þ…+”[Ò^¬99¢¦j1ôì?†îKÀE ªE4p†ãE¤Í£lÈ2y?,ðh ÇuË_ŠZ¥ßÑõFÓŽ‹¼sÖoU¥§ú´#Nø0¦ƒúA;Ù£€-ÖÅe»í¿‡hð]Ÿ`©#dÄ#¡dÍuo²k«{Ç÷¿{tCEm¹9ꉺ¾Õoص9+ÔdI(ñ4tàO®fŽE‰– ‚9¬–{í…S£R+–/vÕä&û"9ñä"±Á¿ÉÚSx¬v™½qTDDµTøNÀ ïHçål¡÷,ŸlÔ)L±4Ç& ¥¦¾áÿi'>–©£uÇQïˆì»á#ª z±={¤ù^TtaQr;¶ðªyµ&:&ŸZø¤YïÕèKàaÏälç1ÁC‚¨|/±ÿ‚Ç3ãO~Ã2,38R‚iutLÖ5P‡ÙSÒƒUŸâä™{Î)"uEs·Te…¦ÇP?Ù°CÙC½ 2öç¨wÔ‘Ô"T™gÉvÓÐÈK©PèºùC^»š¬ã ¶~ nYt&å|«Þ³`òó5â«W8py†FaI“„Åj¢¤£Tzbã -N€ÿ®ØB—–•ó*„,úÞÎþdi– Vim>øÓLëÕëVati¼5 ã±~×OE7ænÞ]èØ@o4× õÃ$ÞµeFW¸åYû”)Ç$}tnÙ-èlØ<‚‘þ_€q%®Íü+ aI?Rž( ±U=z×,6ß…+pW<çÔd÷Ñ ! ~AÂ]¬ú‹O J†³.ÁѪsÑw õq²üçŽIìL'9ä#)øxÎ[×þùX,ãÙ£äÕߤÖme(Òð*-<‰Þ’Ùø´ÎÀÞ힎RbËê(fY,° Ce:å5h—ÐÿÄ'×Ör\ˆ{”æ`¡«Ë¹ƒe÷Œk‘…™ã>çÿomjLályó¹î{t(®´á¬Îj÷Ì—h÷&FèôV(ow0—Ó¦]5 a'jI½ìK[™^Ž!‚Ue&ËVé´§)/Ô‘ O]Ý!WpGª‚«K~Œhæº9Òd«ëÈÔ Î%CöC¶¸3¤â|¬ÐëE‹q—Zßz‹5fš¨6„JÌðú_èxñŸÒáÆXô©YE˜Ù‚<ÿ¯“V@.3ZÓ½ × )ÒP³¤²ÔÕûúë³r7Ì|(AG¤¯‚û úþÑo£à2g—e B€æ¶JI®Ec°³óµú¤þÉ>„±½aÅ&G\2Öˆ7“l¼Dœ\<\“GáÆõ­²H„ž‘r¨ÀîåÉ}wîƒN‘d0öiwÙ±­ôÒ뜮„Ÿb9&êöŠw¸ßßB"LË«ê<Ùútà ücôL$÷dG¢3²H’cRµ@[‘½n”g[Úþ r7휴µ-åJkpÄ— ÷ ˜¶è¤Ä‚j{ Uj±sÄ-Ó†·Ldž—'B#RòµT‹žbÌTPœÿÊ«xQ¤8“¯ÝÏ-Â| YL“zÕ[íÜˆŽŽ™Â9HSÉ*”²±š.PÙ,ÿZѡҗ´gc>ˆXÃ@\’§(é}½^œ‘ʼF%™e!MŸÚ?Ä‘T¾…ÝGIöØ;‚ìc[aùÈ9ôÔõ~‹ 9#k¤&CO’ýu`&؉ta ¼Eû”ì<Óü‹|³˜Iú;À«7Íž½Sk¦@aÊ^"ûí9©¼Q¹&0 Û¿…Å-±u)rCA¬nkÿê4yçà …<¡¿d€6ÜJ¯Ð—Zgy÷¨ùÿ†?q,ãã°ë±ë,†=7^)Œ¸9ߤզꅭ…æ*Âöwì×ËÆo3gh3 ’¢}0ØàWµ£v zàKDºz"R=ØY9JwòÕ{I„MÅ&ËÒ¼ºá’ÃbmPåë‡Iü„…'¦Øåå€ÍøZ,»Ìõ özFЈu”jL V¥0ÒqôìL‡ÝyÆÏÓâ‡É”qôMãÎ«ë´Ø–Êj¹‚ñ-ïšA¯§ý"ÈùS}à0ÑÆ æ6Íb\¤L,YëÞíýu€åòZ/™ÊµkvY¨ZãÈß°üýÁ=õ§¼in~Y[¨/œ.:‰Œ%ÃMÙ1ñ±Oõw‚.úf@/ï'l£ùï“ü¶Iž¸±’±ÑmýŠmõpváê®Ñ(GpÝn¡Dî¦sóê èx²*çq€H¯LË0e4k™«†_šàõ"p.¨f‹=æL-Ú€7,8z5U}ΰðqÃ4\¡5ºü×)œ£¸³<ð«‰Ð9~5wïvßj ÆeB].iH†=Z½ª×ýW(ˆ¢Ãœ§®0É ›]/éífLù/t?e ½ªáÊSà(õÝ2ü9UU¨…`L^Ϋ[n"£SÓ²ìc6n!щ¯ÿÐï„ V7 Lnšî.þŒH†æêomï=uiJ„y[½T~'ؘ ß©=¤_ ! ”ÜçÖ5šX|îÕßU¿`KºECJ’ý®£CýÂjd©8Dé2RµNª–ñ‰fEy!O ÿ¦‘T‘ûNJúkìF‘á©JýÓaô:Ã.˜ÌÞ¿Eo¿Ãš¶ð1æ’Ü[-E1UïšèÜâÏe—Üq“V-⺺ÐK™08´2×êxÀ€^)|˜Ö:¾Ã+úÂ%ö&2ë0½ã«¬^N˜ÀZ7nU=ƒ8$eKYŠç´þëkê8¶ ]2°-¸•’£”ÿ‘Ÿ uêÝ Ëá…Ä…Ú|³EùîµämƸYd%ßO,¦„öC'vU?¡>²$«Ä|·Ÿ« ~Wº4¢jÇ:w hžR”-¾›ð+GßÙ‹b2ûG¿<8zèrÿ%1‘yyåhÛC`à sÑ ¤J|ÒÚÿâÑ•íØ —^AxѪR“P… ‹5(_=UÍs%*÷0}ŽïzM-.Mú G_¢°ìêtÒ³’Ü·G僻£œc9ƒ¼›á©œš“í.b‰$}¥]¸À÷^SDnÚ²F¯/è4Ê#€ÑxÜÑ[Ñn(”,<ŽUgòÒdâ¯|ˆ$Ó(r/Èåøó¬Gàú%ÀˆÖÂ*ÛøÆå]ì™¶ïOqûEÁÍHìÆˆÿâJ€=¿E€]‚H:DÄ¿ü‘Dý I‚¦oiÕOÄ?£k&tå¢9+1²Q¡ˆÒžu8 ³â4FÒ¤H¨²’?ÂÁFóð'Q°Út¿­1‚³Ðüì &ü:¯È²‹ÐüÓ§"ØÚ"”êÊ{¿(íØ»ù:rþ‡'~ ¬ÐLU½¨{§%=£€–ÂIùœ—á#¿…@ ¨ón(š9XµWì;ÁLîŽÞ4qmպĆ]~kRÏ@”@s‡ëNFºÆ¬ÕÍÇŽ¿4O¨·M@ˆ*<ž6C®‡ÃKð…ûõf™4!,u?9 fòfJ¬ÉT Ÿl><ÈÐZqÅUŸ¥kc¸Äà4>¦¢l« á£úL­µ úèõ÷Mã ÉŽ—3™©Åâ4±C²JF ÂÍ<\Š¡=íà8c]|1–©ÄPXã›´ó<¥ñqüßËóï+•cÚÒŽ7;ƒ‚;X Ýxª ;Æ®¼},ôù"ó°Qçô:'q„gâ݊ăY‰7'÷÷ã–"ŠË¤o0E­«Þ`üS\î<×"G›)éNÒ°ZM2q¢ëûÈ+Ü}ÿÍ »%á`æ]}Íïˆ×LÖO¬’™CðÏ:'‚;ñ‰0û•ˆ2cØd£ú©vv Þ°[1ËÉ8ç^æ’õ]Á~Ò¼Ý\jðßþĶ´‹°ï¾Lï%‚ƒ·¾0ÇîwêÉV„ŠëRü¾"”ÿ‘9yj×o!Ÿ+=¯¤»à¾ÁLR,-cU¡…ëó˜UŠ =l¬Ã‡¦â2þ})V+; HÅãžúQiïÒ2ÉUÞ)¹#ºÅç?á%6þO0Ü’w £G…ÎÔàsZƒ Cjiê|ÇÓ:I-»Ô{à«ÇUæôdâ8”b$ÚÒêtw *…ÉŒãS§ù•`=5¨|åë½ý.h´ìµ$Ò·ˆ°iŽÔ}¿¢½çœ`t·T€iŸ~æ+Ò"úƒÁSÝj\¼ýL3;€PÜuÆøÅSÌýðØ%Û_z‡íõ…=™?†–ÌÙ*kj¤»›'$ª Z(’>¥÷8ÈØý†ê‚d ±}$Iõó_(ùç@rZ:aÓ Œbðñ–âVú;Ó_C¼.¡ò€k³¨WÒ'õ$“4Û€±ÞBË=VÝÐ0¼Ç@üGµû$i¤šú TM*žlC¿ [XØš´ÃIa Ôí¿¢W?®¾¾µË¤š¶»h 7Š‚Û.)ѽ߫wU]ïà¶ReEv†‡‰8 Á'Á¢ò'“O¥/&P\¬PqŸ·‹¹ò­ÇÑ$Æçq,bäR´š®û/…êÙZÙ—´>̽î%ÐÃGà;$ }O-#gå*Ý.ãµ&C Þ>b<±”ö±™Ž^§›lmŽ ºKLËþfGõ–÷X¨;èæ³í>Ï€Ñ×´ˆ-6ÓÁþfmü¼Qù¬áÈqñ½3Mk4YiÐt/±×ÆÉÌ}†~¿ãpìVtð×BY4EÐ djÒc•ù¥ðØ]PpO.¾¬^+}ÈÉ£žvŽUvç–´Ûñ/O3Øm¶†Êýë’ |ˆø ;ªY¤hŸ´”nœ*›bè¨Ë)öÔZ¥¨spN¶¬`` g“^ƒ§ÏP?¦ -9J&µ‹åtÜž ã£ÝPû`m™q–)…N_è]©¹é]¤¶ˆ.ت¦yrôÚì{åqÀ4ñ¤Ž„W€õL%½(MHsúªlë@Ž2& YìQ'ã©;—blp±j4•òη™º’ãº\?ïš©2_ª‡Ï†øûÆò¯ÇôÿðŒç?Ý<Šó6义Ӡ,`Êéñ͘•\ÒŠÃÉÝ´–ú뀣ª(í¤îZ†¯¸\¶K3GY ?ËWÿ,S[ 9wœ-¤ÛÕA+ÐÆ¯lµõ-‹PVlú@Ûý!éGXd«n£ƒútÑ&cæÞ Ìbu]ÿcBsjs°Yi¸ íø?8îGÌѾæº_…ô€gÉ ½’Æú¬ùk ‚=è7×µ*!o´ÐDéeð&íT@çZá¸Du"…XJu?²¢Àl¥O ùÈ.ÃŒÐÏ!'-¥²¿æÛÈ$Æ(ÐÞß/ö4. 柗á[³ºp¨‡µ]Öi¶“B¯Ù¹k;ÓªV齺…„LA-ŠÍkrgûLï^óèÊmé¶Ê0¬ô' £g̵XNﴥ͸`0Ðǯª**âùù|½Ë?@ïtœ¹-\\ëðc/ÅreCz˳˜šëƒúç(ß²ò…;*,ÿX 9λo¶eæþÔc‘ÛŸ[ÕÄ®o2²Ü¾ü‚áîWQ«I]¹½ømhw9öËçã‰ï„k\kó×<~˜€¾ZðkÖˆ$gaÍ‹PÔ3½$LâØpàyæ!¿ASmsq͆–‰¤H™³2ºDÅ G~+k‡\$xðŠS{ÛbŽkz¤¬¸xR*Oæ#Ø×¹ïo¯ïvÊôÔúسTØíBÊ€å§è5·©3X”¥mÖ]Qþ§•,Ok·$PVÜ×?Ésš·ÎpÇ 2¶­AÕÿVkÌ’ÒÓQ³³ŸóÂ~H´ÍÕò‰ æeÆK<ï³­œY^”öÆn·#¤J®kÂÔN;¦H/Ž®r¶•m /T–'˜|'f8! '%]íËUÌÒ OÊò|8¦H#„A;Þ(Í3‘KiüTõ“ê#Q†&ë@B`jë[è(}W«û:LŸF#;1DìK9(×LŠ˜}§ÒÆY*§fËÚ8¾±¸š¢}ÑvÉ1EàxKƒ,Á5.` P´T€g¾±L³ª4 í²«ÏÀmšBå×®ÐTîè~ÒÌpƒzVÀO¬·ÛYí1Š|±b†}—š ¬.‰F«Ë 0s…B(Ÿ›´Ò£³×àÉ‘·‚žˆ÷7¼…sïüR‡Z2> úË¡k¤þ\}Kkœc?Râì8ƒ0I8<i8Ïé¼þ3€*MP[™ ø†©L… ÃFC7ÛÈË}E£Ý] ^~® (ÉÜÕº¨ßX{‹ x§S¡#6ÞáÞ^ˆË^¦ô÷Ê«–U¥¶gDwH7xdQKé΀&od •_œÃŒ03ÜDåú@õiš¼+DØ™UÈé8q”²ÃﯵgÚ¹S”ÚÇÜV5fºõ0»5hÓ='´–¾yt±¾zÿ³PêêŸÄˆV™ä»vg•®$ÔÆYw.¿¼€± ÖbXLñkÏÅM3Y–Gjç3Ã=Ûöe§dásà²äuõ›Ëš>tÜiXzÃÀ›cÐw“ßez`ÜO›5pü¸ã¡óÙ:¢·ã´¥áå°ƒÙ¹6MzÅ0 ÝÅ';/†(«ö4cÒ_bßÀÞ8‰?»,ßã6ëºvú7l¼W<<µ²bj=×Md$_ÐÒ–5ñ-—W@ï¿.ËD× ö^¨ŸæÓ_E>˜±ºq,—“G4°'^=fXVRn‡pùfýuîn©ÓõvZ£t êP+•oPRËÜj|$mGÓ{B‹=ñêi›À`ýþ©¿z.Ó¡ß,+z=F»#ÞÚ7U3Ì,ŸÙJëh,-Dc݇þ…“ñ}O1úf«“¤Ò Që}D@xëíDÒ°C¡.¶j˜æg˜-ÒŽmDñÌÎ…Ô‰ì$ª0!‹»ì1r¼&`y?¯R™=ü•Qca£[rzŽê£$Àmð¨]tØtíïè|Úë|…{  ½ŠÕ$\\ (ŒZw@©næ—:aç䌥ó`.X oµpQþ`úЇ¢ñ#òðÁ±uëwb¹ô^$3›ÁA&u®niç®7aOoGÇiîm ¶É°ÐbŠQúO9Ç:À¬û^éê¸:÷ §Š'.ÍìWNæsÝ¥X»éÅÃFO¼xšÖˆ5Ìëg„QH‰ Æ{ Q¤’ ¸—  U§(ŠE_ñï‘&jh«ZÇ£ùü«/ßBᄼÂN@õ~úÍ8Í(tÝòÚ‡HÙ’,¿¶Þýâ~JsëðÍ|Q†sµØ]uÇÖ²ÿOEY–@Øš„é&qΨ¢A,õ®¿“p.J.õ_zÖ¢ÿ¥þ7?Ñ÷Q¹…r5ƒÂò80ðG2–ÅÓwÊt×> aVuÊF4žÓM{ÅH¿ (0F:[ò\hñyË:mó¬:‡ Ú#‚WŒ©9‘ÒD%ô  Óš5ʳ#u´¦Uɵ¶½ç®Ó=u¿ù— ?÷âÑÄÅšXéSމCñ½LaŽ˜„¬‚jùþak´Ÿ)i€µ»‹@¯MeMkïoy%üQc7üëN!®Ê£"{Jè…:ãþïZ<šd4ޥЎ]±Å}^Զ׈Ùõ6·¨s–T„"ÎóÚíw,kÄfU0‚@`„ˆ%Ç/ïR÷‰Xy°À…·oñÎýÀÚ„èÏÝX‡kçk“æAàpáx‰2w¼¼°Œ=Be¢,×¾>œ1T0W×°æGÄ_ª¦4!ÙŽ 8œuH¬ÿcÔ5w[>*y3Íu'¶Ý ÝÊæOÆéuߘèऱ½ú·êUz•]C£ÈÇG[ò3„Öa£v°¡ÓÍ”°4GÁö‘†ÎGlÊXáÉ¢EB2å\°…=|úÁúÒa‰´ ¯«ZT]ª›Çdüj¨³]š?›’¼Ìe  –íBG3uQ’²3¸FÉm0£·$ˆn¡j6F¾8i]i¹Aú?Dv´Îßùg›.•)¯¹ûÈFd•üº{³  :å êEÙäËȬ¼•›­u ØÌ@sþÎ×ö¿£:9(–¥åŸˆâÖe™Së¢ÜuP}ƒ&«uìgǯ¦?È£†í¤ôÅšE£íwëéGÇ2Fï€2ÎB»¯Ìf¶°>g—“H½¦zÚÖhôޤbéÈ­äTŽ˜ªeF®Õ ¿--cåŸÄ%Ûç\\!ô"©ˆ§YX ›Ê bÎÓ<à®—a•ÝZ› F8XÔVPg¦BñÈ0{—Œ˜ÊKИÒ}F_}÷u›6éÞʲ—/y_â{@:“þþrõøÆ¯S'~«×M6¬³¯úI ž¡’©™¶THr3ä~ðvj1åg‘›ú°Ò`è} @ñ¤š­Áué·¨Vt±e€¿s­ '¯PבÿIµQY=›Žp »w öFK×À4I?ÜôNÚä5·|´nÏ5 #Üs‡Do­eHÐòô{y5·ËÂtá,ЂääO6ÀzÒ\»!ã£@lîzó݉nOW{:Ä3ð°Å¨¶ƒ•Hè›onXåÕ‡y±Šë³²þ¿J‹³o_u _2r÷‹‹›8¤ gÙuÄýÃ;}¡U}½d2šÞ~»Vbngw͆‡pì¨wà|3y´¢M‡yÐ]ÛÒÊxxú’IV†ãˆ<™B”óî©r„ÌUóo†Õ­œÄ„°wÔx4RÙi¾ëå a¸FÛ;¬ÓäeД¶Luý[ kM:± ÈÉáóAÃàF¥ðàžÏ¶Bõzê†á™©hÃãÅè™ÆºŠð 5Ää¦åDN^—ÿñãí%ÖÔg…á2=V=÷ÅPdžS¯_áÇ¡òÊH,PõÄ_zVt㙂nÌk›Zþg¢Üʙۡý+P²"»€³mçój¬ý¾&ˆ.Î! ÉŠ„ü:Í)V¿†$™Pÿ<,=ÙÇM)Û%ô%Ý šýŽÈœX3ÒsTaÐN ÛúïPf_Æ-~¦‹¢£ˆãÄC{6W·÷ûƒ30*½û(´@ÔÏTë„U]­ï0}-ô£±ˆ¸4ÈG/\¢ÙP¥EH ÌDKZ)d¹YyÛè.a^ñ‹öplÊä1扮YIÙÊ8üó÷\?‘Úì[?]ȶ6iŠxi÷A[m*¿–!­õj¹3Ž¥ýñ8²DdDÜÕ=·×>®7<]»ç¥»_¦ÄûC©Öx¯‰,h¶$‰pÄ·«á°x£LHÈþí¼w¡Øé6ËÈ£S.Ò‘.³ï=pžÚé5»››mŽ™¨ÞX×Í*ý¼ÛÍGŸ‰acÐëT2Iã¼¼x‹¸¯ÄæTê¯ò\0joâ–»ÑT÷u/¾ YåU– ûrWh©wÇfaÒ[ ˆ 8€€Èi0ßõ Ï­…Üüv>vÛ&@ÉKŽ”&x÷›oTˆ}”Ã3Þ;{¯HàÌ2µcœ©ù RϤ=ÔòëîVg»53e6ƒN$ÇS¹9©Óû©¬<={Å9 v>d$ûk ,³DBb¤9£ê9w¯@ê_®éÖ:‰‹²¥R7w›Yai%¬µÜsÄèŽ÷ÍDù$Û_F·Åv)½Ã5á±>AtòZÁ·C”ºõ«Žc^WT¯¦‹æÞŠiëu@ׯÈÅÿwdRKR‘D³”¤T|O'efR7C'ëjÉÿð >ç àÕ^xì÷逌Õtƒ)ìâĈˆ3PëM0Šò†Ë"$CÝ2Û Â€ÎÜs çB‚@Ý>$âÙ×nt¯4L”òJ!×5Äáøv_Ñ;•¦œR’9šÀ×¹AÁŸþ1×ÀŸ›wbè¨PBøL( ž?h®Ð»jÔN4☆FuŒnšO Bê‚<ºOr€@Ò ˜¬—Mf¹Ý'gT÷óŒß·^‰û·g²yH–Þ;qמÃMYÀúST^ŠÏ6Ä-›)xŽ8ÛSÝ|L¼½Õ™ñXà>ÔÃMš+¼’ÝæÏ2^\ È^Søì,´h|vg—Ý™»[Q¾ø„Fò1¹¥Íd• ÈõŸƒ ‡ R°À5ºÑÙ†­FœØådPMAw; (m ³®b͖θPAõÞc¸ÒDA6û¯ÙTܾ‚SIå–7øÄ*'cÐÉ’&@åúëIb¾]Ò­Ç[ÛZõè"õm´†PGSŠƒšIîEÈèÁ¿ëk\ȹCt¾'Ÿç;†‚ò™Ô€Õ õ”%——ª'¦±òRwÿ„'R5eï@šyΔœí¶[‹ÿ~I¯‚©½ÔzÏwe]Øjõ^Îqz»%]ùDCQ‹$ÿ 4ý—Z}l—Rç„ÊPýÊ!Ô±¤l×½”ÔméÐ#PÆAQ+§ÉPå“M+ÇNS¡½ý$t4+ pœå‚ä­ÈÞ]ù4ߺŽ:‘ÐsB!»èݦJO{±-nÁŠœRÆhØáú%&˜·½â®è»Ý«… 3Nì#o\ÿ,ó·"ö±sj!˜ †ÿ”Z58~2Ï${H=ÍÏß–´Šáº.K*a’•3ž,šï5¿ßäHÏr2_à8 ‚ìÿï93‘™4±ôŠ>#üKM{ÂNå˜çLÄ8\Ç9¤Þf k¿fž§pßSݱKDÛ1!_¾Á¸ß 4Ë›Æa_e•+}¤úÜ~Ø”Ñ Ê6éÇõæ«Û&ûu†üš“ wº¨:ð¶á³ )ÙC­ õ±d‡Šˆ¤Áá"†8ß*ºáän±ƒ­¥® ÷ÝDÔŽ4YÅó¤oCaNºò½×6þ’€˜¾‚žA»©&Ìr?Ê\~ÊËgŠ®¤z,P±,ÑKo¯t£(Óîñ¹¸?<ÖNqIŒ/ƒ”Æòzºó<¶ fט¬:ËBr†|l4ã¿w—¤ìôýÇîEºîr ¹U‹©þr¤éðæ=j#†nwX…%*$ú³I©…gƒJTù`#€ø9ÅŠiÉÑd`§¡ßßÀS¨5&pKŒ2ƒ´ß꣺µÉVCÂU°1¯íËzÅ¡ ‹Áù+¥SbB‡ª_b>›òÎ$N?0,n€¾ !ø’—}pdÜ-­„_EÚ>ü¸j¹ŽlîÕÍ/Ó€‘ÔþL+%*&¯0[ß–·eMc…½ZÐÛó*ù1íŽdÈ¥˜Õj›ŒèûcÀ»”ÙIÓú¾ÓãV§š8D|ÌIÖ™øbOŽ9jÏZ}àw|¤¸y=´ÜƒÚ¢yŠ3ÊŽêÑ:¯°ŽÄd¿TýU|˜Ñ1£%4Y ñ»YQÕãghx™4ÙÙB‹ÿ§)¨œÂr±œÁýƒ¦Öt·¢Ò«5À½¯# vCØIù8¯všêÖ™ÄVª¢È±Uéw–)” ÁŽÕÊ:åkOïIfN€{Ë8עРn#¥4Uõ8¬2ýZ ƒÖ%•o ÓзåèépÞ:2óRžÉü”0–n6Ÿ“çƒ| ‰žèîr²®ú‘-”“m㥣ž ÞÞìjŒÞ±µCXž@Yù‚ýK…9ìØAO°¬Š$»á¬î$@$#Öº'.iý^ì Æ ³ŠOÚŸªÁS‡vÚÄô*\“ÛãÜx¥1aË{̓´Q!¨ hÉ3y|e~Õ¦_ xÂ_º-µ¯пîèl5·-–• ûDRÔiÀ¸j6ôf>%Dó eMÅÀ|NâþeI÷ó…— (HÉ)Ø7b‡ê"mô£ßËñªÕjR¥ßkÄÏ4c |Ç[cÍN·äXAz°§Ÿˆã–“[D¡CÛΟ æóÞÆÉÞWÊ2[ЍXúhl<ÿÑ.ƒ&]è줆¤ Ìtõ¢Ej‡‰™ýÉ!7!y¦Y<­÷0ùÚo·Áª‹¸‰ ô~£ûèB5è&Ÿ·QýmïyÉ}Z}O†Í`…¦vøné^ºÛ ™›óǯô©Ž$¥7<0µæYè‰ðý€×àtÂQ"ûõÿ•GJÙÉ…ÕÝ™ŠüåX}b iFHn„‚Öj€Ñ ;µÈªó3;ë…»˜Æq?!¶‡– –O’Û7=’Ù|+æÓ:?ìÄôeõíÓ¼ÃçîRì•·é×îS⬠k¸:w!}'œ¯l·°b±Ó²…×îH*f‘WÎo¯]‚0Äå4ŠJŸ]\òg$Ä ¶tèRz2îðÊ»†)¯É‘ß:Ä;ñy`œÿ¹F­›¿™¬¸(+ØmÐÀ1 ¿·8ìÊ»9ö!¯ïQЮÖV3»ÎB-x~ýYA¥—šÖã)ªµ{5 hÌ‚ ª‚ Æ)áEnŒ[aƒŸÀy+²®{zÑÏ'?aøŸŒõáÆ(ïx,åõ\Oh0$ØÚ $‡íc0ÍÅOŸ°j]¦.ã¦? ÷¼ÁÆ¿ç=cwŸ”x zä)˜0DÒñv,ö­¼¯³ÊHN/Wɪy8Œ¿j˜ 54^¥pÁ>„¥ŽÏcÿ)ðð"‚CÐo8…Ÿ›·ñŒsfú­ò²Ÿå¶"]”¬èxãn×­œ ûÅj}ÀŽA<Ÿ—fé.“~tG2ãü*ØmD‹þk¡[Ô Oû’Š‹°µùËÖ)ªýQF%é?y’‹¢9õñ‰ÓÈž ®ç‘ÊDšmüüÏ÷ºö뎗HÑ©Bð½ïó °ñ¤ac“ E”׈«iºvƒõ7Õ¡ ª‰~’ïÏ_eY]qPó¹ç·¸ v½ñ.,Jóûøp$*T¸!·~³€§1©1̧§çãE<Ìô#â¼åÀš Ä ÚèøÞð2û× 2­ F¸Ù·å½ø²|*ªøÇ&Y[¨œTY–·2fõò‹¸2¡C–VVvj· ]ΨñèÔß<8m‰îãPd=ƒ’2ÿÞú¦›.1[GS±y5X’ñ=ú41›†7ÀÇfZÅ÷1×–C˳põ¹œ§8Úù¢èn»8‚Ésò?…J|èÖGû“eÈÈ;¹ä)mVËm¬ÓT—õ}0<–¡Óê$,,Æ¿Í6Rfq9œŠ¹ãC÷<-ñ À՜˿@S*fmP¬Ë=‹ CÁì-P1›ûfgf¶ZûO—á)—m¼ãc¨|n:)ݶb_xÆ—¥^x*ªb‹% &]ÎB¡8à ^ã°¸%M6IŸ²ÁváöÚÒG›üذc.jÊôy­cM7 Bw*ó%Óß5<Ê %û¡ ™íÞžÎU€; Ò y«n0¹[ÇÞ)ài}zŽßÕ{»{VegI±r‹øio%"0M–e tÓý+ ŒoKëÍ®\Š»zúÓh]2%#¸ûºï"Þ`ÝÓ‹\Á|*(«Àgˆ[\ìc#'¦ò´l0£®j¢3°E¡Cöä+â݇‰¶ðÛœ&”^ƒ~ip©,V ë4¨µQÃÈ&¹Œ=è&š[YÙyé[]]Ra}B”™LC«(áÎÍ\Ÿ''8üèk ~‘¶?&·¤‡¤Hg‡xš¶7=®Aä„öDï<^žZ5ÕC©v8›šŽ2QGl%ìKoçSY<Öb¼¢h‡K¯eÀÔpç´ïÁ†‚£S*t³ ýíQœ1€Ïj7ó”DÌð*? V/3Ö®Ëð2SN’C@,Ò:S'‹‚y¥&ìÓ– ÀŠ-ŠÎ7–<Û &ê=Û’vô…Çñ4 Ó‚})É/µÂn„H-"¥e‹ÛºHl‚*˜ õZû探¹±§³ˆ®Üa¾šzŠÅ¨-TùD#,ÍªÒø‰¯ut[x|®©Î©qN>ÃIqv@–ÂX‰± X4&‰V .^¯›çlâø,‘g‹iºG ¹ƒBø0Â^ѬæéêĺȊF£7êSà‡#0ïw¢i¤éEy“c\^_Åt§ªåœ„-SŠ™ï²á÷²S?'õŸï1~t+A}ç‡cÂþñîL’*Ó–K?M¦$P f®hVu(bôU)]Â=q„LêíªR£uʘ6ò­'îà žf¯5 RC=cm CXé9æp{–ÅŶ¥8“3©žÂñc1Vƒá,6εOR÷,3‰þ:ŽR„{4ãÁe "ò†©çäZb`ãKãÿpI ˆŒëòÐ÷û¬Ú|Ó r¥‚Y‰AúR õ÷ð ý°ô¢ÈŽ‘YèTmÂò¬^G:¯ÔÙð!Ó6ÞV3|<\:^) .~ÙþÛdt=~z‡ü =ÙíÂøÚs%ÿRþy‚XuwÓj îi¶ÌE*ÿ<Ȇâÿl½—ö==”g ,¬˜Ý .¦´(³j“´v§r‘Þ‘†è3¼Z ÄР¸ï_±ÜéÖç¸ÔšR8u‹ žW µ ºßqzÓÒ²aw»øtmÈðïÇW+xw~v „ çB¶}†hqÚ• ý&”RËµŽ®!¼ÁȤÎH+‡ªÙ{M@͹š­~G(Žä—^¨ˆ`|ú ˆùø×8Uãú’ ö  CØÝqá  ) x±ã•ÛW &1÷['hó êØÃV¨ÈÚÒõbÁ%­h7#"Ÿ4~‡Ľž@Zÿã:¦ä.¦£aÿ™´Ñ‡’Ëb¹®Äy’¢5†ŽÀœdòàΠÀ@¿#÷J%X÷÷?>Èv,*Éò¾]c>IæÑ pÛ¾¯<ÊkÁºîپе.·b”XR(ºYò —Î'¿ ÜUgº8oëô渘‚–î{­èq$d΋t™X;G,ï£cp¨¼ïó̵? ÂîØðÄÚKKÿ‡»·G+QÂþ¤eo€ˆÐs³Øx"›ãGg€¥¬æ´É4 1R-ÑéÙ—o¶‚tÀgTŽ·‚¶>ï^Ýß:«kl\Šˆç!@‚QÝ =¶WŒ_&`UœXÐŽm–LÌ·q˪.vxzg7ø^§ÎYÓYgl\°óiÒTïŽRÍF×§¡3ãhûö/Ô¦õHp h~L­á’ª^yªyêÂÅW(”?ïý¡ÄM"Íè |c¤T-5ÀÒOWÒÈUìP[ å°‰I†šòpû±/ÐF‹Usžñ=÷Åï²…CøY䄯âL`Ç]À(ƒ·ß¾Pì•SëÞ!à’—cöa"çÍ’«Â1<©ßƒ‹.û%¬º §d<ïx¶7áͰÐ?_Áý ‘°"müþ¼w•¤¡¼¦w8\4 Ñ]ãL™4ÜqÔ2i é»\ÂógßœSg¥C´v¾RŒ™Ûþ˜nªþ²*8«ð oAš®pÛjg‡Áj‚ÃHÅÁçŠÊ™,€ùàëä²…rŸôo1¿%djüxFì dáâŠõ( WÈ]át^=Œ±•ame¹£|õÝ´¯C±<¶s$é½ÿ$Ô@"Y7ÿPp5Öк^ƒ »CÎ Ùú«7XýÓQg·Ž?•£«KÁn=¢ÿå×ã bÓ¥åõ¡EÝ(FnüÌi©ü“ŸœAPæ$Q`ؘ0Ln®öz¾Lí¦±í¸CÒxRÊe©­ád°&ë~…Cç@ fPò3øÂrRãxõ,ƒk˜\Ç€tû*Z Œb)”Ø1ÿ²Ìà<ßló]™wÃ.‘Åï>IFH¿]98|âoôÊKâz=ÕI¸jHÚ ‡ â;º7… *ä Ò%EcÁ-Õø­>‡Õ‘—^–ûdˆÍù]ÈB¤ñ³uÞÀà 1¯iC„Ifgc™M‚ºá6½0™þšYÀ†—ÄOþæ‘òèD—ØG}®m˜NrO±ŒwH®Uºº³Eô_Î$&Üês=ä]Sªÿ?nßìf"á¼—zœQ%F\W žPÑÇ; òÇ…¨o”=”°N…øÛôƒØš#îÍ#àÊJgmýiÛYef‘ŸdQN/Ú.GªÜ³-Tµi£&Yôñ‚Cj²ÿ§Eë…o¨ÿozÓèŸ"á5]Ì«zñ„j­Ì›óæÁáÇÜŒ#—‚§>c¾šºßPóB {£‰Éô:£ n¼JPy<ÄC) Z”oò…àCì9Æ.(Š%1~´ZP¼©65O†(Ù¶ ôXÁ'ª™Åk¾¾Sì×þ÷­ð;eàž_µv·ÁÙ õíç`»ê!wÎ+ ¬¥„æÐOl:xO±Cíè]j÷«ß›Y(à õIÑëËî‰`é€U^Ð7G™ÛyÆ{.Î)3Bouî «Âá/ß2*HáÜX"ÐÂô¿Ø%ÖmQ#±R¼n§ñÀPˆÖeeò~8Þ“ö)ÜæÞT:dºƒ^بxs[p~ŽE¯²Á¶êÑï:€ ;‡&?K¼‚¡s°CñhÀ½6øI›ö-”8™ŸÅàÓüÂú…0˱]ŸXÆ>IŽfM¨VOzµ!_”‡RVéqüþí¸fº«;¹‹`Š›INº|@B€“}ÜšÙG˜ÿ|ændVp,–ØÏÉNõ ö¶1ô-ž<Ù¢j<ò*(ïÞ$ÕÞ’„ =ò„†c}£%;ç?î†ã‘è!veÔ%kû{<(O$3% ¹iâJ§?,i75³?{/~æ&üÁ›³?“&¦9é²ì€·~ýGKïR¬Ã¯øûi #û!Ä·/å›/´©Q½9®5<¿ÂªL›';И% ªÈQÀ¥Q¯<‚ì O½«Êç\S»í¿nÁÐ8g}sÛ®-¨¦Jÿ~b/‘ N ôi·cÊÀO5º±Žä>BÃ\C­ƒ†‹…•²ìšÐãæš)‚{$ô’àÔOªÜÆ8×èåäx üÆœ;ÜÈŽG¥¯ 7å ,™ö̾r„s Œ‡=ü ‚_Jƒ|.ÅÇ Ô&˜Õ ´ÆÏð¿{ LâÅmž#ù/ZiRµ€ÎT†Äí¶•« ®@$›’°ò †ïó„±cÊš¦üSNiMëhÅ >ÝÎI}[ô_0LVLeLÿ>¯N\4.µi€ÁözTÔ%l[‚²ómÕØ¼ g—ÝﯹÀ"›V+Èe6«‘T p"š9Ucl´ïÈeë,ÿÓ:öŒ›­øAÏÞº?!r˜Z+/xt²@ÇrªÇQœwÎw ø[Øï=‹ù_½¨þ…v•ÿôtу¬‹|–j–¡/.¡yÀ,¤f´óñ„.ÛFõ­álîì¯×EŠáŽÌÂÕàYél]__f¦Kóh a§¸óenÝ6€|çh‰å;Îg¤ª #sù—¬“ö¬­kœeè09v Ëm_ãúº@¤ÛÐ2`Á/ 仵UI 6ïZæ/9³\T¿–ØïZÍUÖ}é„ik _û¼‡Î¼Tx˜¿é ç,ñÐ%sßàE­¿9„–¼Â,#éò4¯<qa›J‡ØÔ+Qš¢L½;:)ÔžÊ2µ6N¬ k나ro´c4é†=/å#¥p„ƒRÍ‘j«0ØÑÉ‘$Âd*L‰gÄ| ›4-[ÈÝ>™C_õu†Õ 1Æ­š îXX”TmGQ3è†G:¤ø¬ØÍuEHûDœ°ÚeLPàìc¤=ý­¯dô#5˜oåK9ÑdD6 ïcDOÃןK:+ËhÊ ROvlœ“»ŒUÙZ¥[þ+3Ô`{Ôv¤r¿,c+Q“ߙΚ² ,»)ÀOE«®„[$30n÷¦Vw.¦À†‰‹²Z".êùz+Ä¿ÿU:SDºiœvBÉ)½ÈV(/"J§aQTSKÅׯ%"Zuw8öu—uò=ߨi([€ò—u$ اé@7¼ó- ¯{‰ÁÀa^€0òçúQ1à?OòU8qçýÞYØ(DOÖÙä'å¨BPK•]„Wc³’hìÇÄàÉä#?vnøEŒÔП¦’ú¾ä4e÷˜ï"Ý:®1îØ‡Pûº8Î5 ÑoQ§½³ƒ¢¾} ƒv»çW£‚ÎÅ÷ÑèffýŽ ÜÐæ¨Õ”`‰‹ ã ÁŠbÚ'AßVµ»VìæRIÊN¬ÙFCÐj\ËX$!¶lƒ¦©=¡67YxØ«‹T®èikzáÏÜÄ¿BBsœGIÝÈÔÀ:ÍËõ„äó4‰_àå*èâ ߸½SÁÓBÔÄ !ì$4Þñæ£gX§â2pÜ`äJ¡àr‡u¬)…«¤ïNÙZ1,½iS{ä±*ÞOêk%iIC2ÛLš×Ô@…–ÌŸ™Ùõy(“ín‹ÁV,çÒhmü"kôBÉÌ[°^™)²GýjíIóÛó}=bW± äÛ}-?üÂßÌŠ~©Gùï®c€<átI¹Ë ¸±…\¥ÑM^OLÀòTM~}㵎Í´\;Õ¬cɉ¡¯G‘³HÆÉÂsD·«ÖO 6†ØåNÅìâqþ¤9¨ Šr=ˆ$ÓõaC  ú=ÎU䙤¢XþDóÇ*²yÅuXß“!-XüTBëÑ›(Äþ¹$€ž©$ ‚šZÉnPJÇ$h%JNõˆœ„Ï*ÿ߇d ÷(kº­cn‡«K°è÷gk^žÅ©]†æk½¬h§­L¬¾Å¹ƒ¤H:F›Eàò¢Omè÷%HPÁŠi=»W2;“Ó1(†ïH BÀð(*JYå}¤&Ëp]§Ää¼÷«¸ˆâq#ÐmÌè Þl•¸_ó¤8e ©šÃ°“øðmüøôq%ÌÇÊ{õêH⇟<„_X•y|i‹ìiÌê¹8Ü»˜èeï,{ZÁ}Ó}-ëJNÉ´¦ÓÞŠñä½öé¶ðGçvC}'í™GÉv¢)K†7f¢A@¦cR?"1ud+4[0¹©ß+ˆ«}å çn¸/¿ cå~`á‹‚38{h/'ý4ݵ ŠÙÜ¢™µÉÔ×ò‰mfQ0ÝÀÖ¿†v½60Ñ¢'v_ºå…s;éÕ§ ¬ü°œ›/ǹ>ÛÜ/iº1Ïw˜üÛ éµ—Ç)ñ‡çŠ:ïV+R „†Š2V—òe‰Â³ß  Fƒw(!ƒüUEn °?2~máOß«¼}ö–ÙŠÑòÑÐjô*ÕI¨óR|?Û³yÓ­9µ¦tC¨‰F=Œ>PQ:uTU}É”ŒU9hY’ÂÖö/_Ê‚µGêÑ@q‡åy»y£"½Ë÷ˆÔÓE,T {޽øn™,™/ :‹,sŸœ¨ãä™–¦Kÿ‡‰=.³¿Î±Ee^ô[‡(·ü]À‘a@½ûD×Í£‚°B[PŠÜE?çG^Ê6À¿»³c×¥¯öümUx1@3 Œ&Â-erv嫎t?õËo΃_ô ;˜1ÙU‡2wéÝqHÒõ 8+…·ÕB÷>›Ó ®ü#{r s…#-]¾ÛúÒq ‰Î~éW0ipÃW|2˜G3WK¿F«' ͉¬˜^4ZuTlfíšËø ¹qeeú=ôÛ‚÷nX/SüÂ´ì€ ïŽíìag[]?84VѲáÙ{ã½JçÞšj  ‰Þ­+ºëy¾æUW íÕû9 ú´;x Þ¹‚z²aÛ¡­M<…X¨§áÕŸbµÓ…J >ˆ¶²ÓܸVO k·Å¹t/³ÕÿåËvŠÑúޤ-Y¯©O²ø`AÜH¬Þ)±Ú¿|œp¬5–Hè,×8*áL%$$i[òR.¾#Ï:V.ó»`Z³†Vó˜ Š÷ºÊ:/©%¶l€©k}öR{B¹§;”(O¥ŠŒn ¡÷MœYŽ|à¹DÄÍ–q¦$ÿ ­lÆÜH¿šßä$!êÉý_qŒXJ•¨Wñ ç¨Eí»¿ 6C9u’¿É ï-ó=GÁÕr_ -ì?’EÀŒ'  0.l™z=f}²[]þ˜LËEwnv‰"Úø’û2zê)WM¤P¤ÍòlνÉmh+â·KÌèÝϨ¥ÄPÒ*Óg,jïB°èóÈ_öÀ¬MÛZ·O˳Œ;PØÑe¸Ìöl‹@Iã@H@•¥«þ§È=7Öž&¼Ñ/¡ˆIæïkº÷‰ñ,_Š7IÙÚp9#†sÖÑŽöù·Ë@WýiÁaн1ÈšøÁÜ]?ŠÀs˜­ºèØü騾˜“ è·F§z1ùLÉ_¬>?C¯¸?í\sFG·ë_¡TΪî-อ!_Â8U=¾Ó)–¾å$/°ä=­©¡á‘Ìa‘@ýy|XiaB/¡Ôõ\ÂR^º)ª‡È¢„~i‚þ½'‡­GMrLšâ¶¶áS „ë?-Ò|+ÝúÅIŽï*/l[`×°wîð¶Ê²ceàW™gÄ”¥+èêÐõÈ4à¨JÓÛ¢NSÊ«Êí¹W牲•HÞ«tˆœÇÆqq«¥¯ôø…|M¥CŸ¯Ëõö.–Pž0šM?‘å¶?Ý#ÖøâzE&¹¹ßÏ2–äÊO µõtñB¿L©[¼ƒ@¼—DÅEy!v5M`ð ly¤5EÆ€”ä*[¢¶ƒQ$~°”î†.C$:àåÏy8¶ÈM5eјҒHÞw Å'|…Ó¨ìâ·‹9+­–ÙH¨¸sÆqðŠÚÍnº e&|k–½ñÓÀºëØ6·U^ܾ»ŒsSj|ãkU ®êpN îîOI8ôÇp/-­áЮ`]/ÿF„Mï–2¤SU£[£ª¨äXíÏ#µ)c}2@Ñíb•)p ú}—œÌ„œÜ›4CWÄñ*cS¡)³7ËÐêu$»¸æ‰¤Ë|õShÙNQ,ìZɰþ?þû‹ÆlkNQ©‹yŠñð7)Êçš W$ÏEÎj [º=èqOpÏsu(`³åWUŒ¸†’Š‘בã%éL6.¬n”)0c’Aå²]ÝÒ¦‹+ûg[auØ0‰—:GÁYm¿Åêü<0SÓqÚì%£÷92î}HÈbÈù“¿åA˜òG+µ7 ®š\«àm¥Ô;H7ð¡òáÍÿ¿ÿ3ÛŽk¸Ùj#FÀð†¸½ù#ôuÍIFprÐVûeZª° dú&^ ­ñ‘Ímãð¹›87 uÿ°_òH¡·,o48Ÿ"üãdWÇÑéÏóßW¦?Ñ|‡¤o/Љ[ ßÊžP“5i?^ªÚz`M 9ÕK¼ZDgðV.pÓ’BàíH:,¢ƒ¿vvX«n>/ŠqY}nqö»GëÍÅb@Ê…/:´‚+ô"Îþ³XÖ¿r¡”úÈkïR¾ ŒÛœÖWÿ¿ì–yº{mc‘¨sjûvw ö­|àþQÅRWtKyÚõ3†ßç'Æs)Ýfx¥@z,l¯B÷õUù/A›ÿƒ’[o ¤„ÞÒT %Y«cOéØcêóÑ(À¿ؘ}茉¹›FW2µ +Önd4Ù®Rƒ¶'dÔ@†[W Ñ×ÃM5˜¸ïIŠb¤vT{ O^}Q¿THõ¯ËØ×”˜â&±öü g½Yv@‰ Þ¾ÕHÊHéhL¶¥¿0`ºþ5RÕFнççp1çvÄŸÑ[^•o„ü\øæ—çè_\6bŸ¹µ}ŠD—[zƒGï»è'lýîLo5^ïðÏ2ìù½ ˜TÓ'ÇkNS™Þ"öKlhÎqûÞ˜01ªS"p¿ß…”Æò<±(Å£ïÄZ“Ë–UF½ÎC?nFç!Íùœ,‰0 ùNÁ! SJÃ:…rÍ-×ýˆË%‹Æ£Dûê§âÊ\hµ®ýB =)$:ïY\35_YŸíQùsc¾C½ï…T]íB4 bq‘4›oY³p|ì¢×3>í-lš°Þ\,±4žµhR$‚ë°ðEoþ¼¹1M|ÂÛñöæ•öã;8»pe´Òõd‹ïý–ÇåQ.:‹[ÿ0d¦$ujp9w¾‡×{¨pÞSD¸ üµ Ûw7|wx&Ü5—XadB­JRk™ ó3Tô„¶­þÁqJÌüPsðÊaO§ÅïÊå/S] \Ôæî+Q ‘v¬á[dAÆÜ®¼P]€“Û¦ÜZÇŒxZ+ŸªœðïÇüœC¶ø ™”ÅúYß2|) JˆÞ–TœÞ~\Ú:¤ïøJ‰á›Ïh\ÑÕ·š û²9‹K¾2 ?nâêOÍQ—DKÿœšÐõJÖüuX5,ý›úˆÊÇÔæ|á­9ÃWœZ Çã!pæŠð $Ô”ÒîÇëMÃHΠFæGééy˜žÚà9Ÿ¬î€tï5)+à œU‚|•¨ËÅsd}ÄóÚ<͆aAàâÀ\Tœ i] ×ë‚~…t,Ù$N†L}&ÈçGyZ1¸3W¶8¶µWúù¢@@m' èoÄCq¹Æžª¬è Íî"8Œ¯0„xŒß»íP—(›â R‘Ÿq|#Æ8Š©ü8›ø·g-g§Öo]êè÷ê8ò'©«‡¼A뷤ϣ„"¦D^ïvx:rÀŠSÔnPßÐäLHœÞ¯Vô‹¤ d›Ñ ÆÓ«&ÂÅÖÒß|Õ†ËCLMÖ•ðøå—Õã%= êêÊLûU†áe5œjèË.ußV“q®›s*r3]c~k¬êiV†¨Çh™|„'!F8;ÅSÈôLJ›X§QÄTIß œ‡D\ ôx« +·É6§^ùð­žÉòè¼âŒÓµÿÁ«~FÕ{m£jÊOöýy9”-³"f=Õ5N•̰TÎ)éðû~+Ђ¨‘¡,U J¿²Íû„ýôhé5šj<žÝǯ›é- .‘eì_¾˜\<„AŠÁà$/—¡gž¦ŒŒÄ-¸×ÓèöÀÒR,Ñ™b&ÿŒ•m? 7õh¦sŠB#²¦Ø|Z[¾uî 纵µi—üG÷žLê;G“Àp:õ>Ð*œÌÚèè`Ç¢ÛH]Oh¢‘K®||aKPÔåW¯ ’ y0•Êsšò/ýüU ‰öªŠF¬W4‘<”¼ä|Õ U¦ñfi¶À0åçRD[œÑèö>µýyÒ'ŸéFšEöW`(n–‡>"Ó‹¯Ø)——HóÉﺋ+­Ú tôÔëöÊÌ‹Ô!îš"û)bMºC%$ñTt‡ÌznUŸâ¤C”é,¿GDëŒ`ïin‘=/×Óe€°ÁÀÁ¶yU4Jd«*ܪ|‘#þ¶\+¸§JXYx"@B‘…Ë£–]é|Ì#x·Ý½7Ó–#æ uÊ(ÄÕ ¢?[Øô =À×ûÆ‘xõÍÀMGåv­~OG‘JÑ!†"CVÔ´Ie3NWAs= EÖA·(§Æ]_s?Q'ž¨ºö£ “œ$E×Ô_G3åù`  VY•Ú§ŒuW’~AB¡Ó_ì•§‡?gŠDþ“{l'¨|è—=ÜÁû¸‚H…ÕF=p¢©ÿ‰ô3l.vùÙ?å¾M·bI$Bä9bÃß*À‹ÊJ¥î:ú’˜Ô™Å½´Ï£__HhÍ·G²?Ü~–ök¯¯YmM»l`Áõìj£}÷[êiÚngX€|?ºçûÿÚ|¦ 6#?£èºN÷/ +ãîQk|ÌO SB®€m¶(´J<ˆ»GP‚WF_Ú' ›×oÖW.¨"äÞëp*¡£î q,×5y¨‘†xÈž(òºLÉUísH «¦_”ÿ’ƒù$:µ'xeg¹Ü°3s§®¹>'v„ôÊ6ð®úÝ«„biW–EófðÒ‰-ªÀ'w­(ók«ŽŒÍÃìNV`•ÇÌe#v‰f9+°cí ‰¢&‚¥Zvä'þ %1ò8z—²ö=ܽ&é¸ÒI××!3ˆSY#ÛÉhhµúh~±`$êžmÜ€±Sy€hŽTå¶[Î8>¶Q\\2gªñ¥èvâî`è—ä¿ço·¾/ožOPu5lDÙ ‚D Fý±ÿØŸŽ(iø5™Bf"É—©ƒõ5("A¦±롈hCƒWìMFZÜ"9EB~Û‹¿Ïº‘ÞW:î¤{7/Zó–ƒg¼Ï}«ËL”Õð³zYÌ”_˜€¶‘È{ª–âXÄ·ö¦¤jYM'›á_É&Cm+&}ÝpÓ™øÎnXGñpÛõ–EäÆÎÑAô*Ä90 lQYz!¥`âÙ¢ì‡æ%<‹SµÂ%D Œ”:Ù‘Ž™4ÆP·eQ·IÊ•ò ñP¢# ÅiegcBTÑÛšcúuÁ¯ÅRåqgüôNìðñ$©Ïã>2ÂkX–„$@lÐv£®Î›E˜YâP›ãØ3 t I0ïõ8\ì{­1‘™TL1û;Ý ²œS©ÐåÜÜ¿é’Õ&Ó \­?¿Höï ïcŒ_Ø9\¦53⬛T³v­úÏ}ÙÙÙs“‡†¨Õà{eð¬Dø® ÃT¦¼¤)E.Âgø¼;k]Áq„Y¢ýÅš;µ­Ød?§Ò·UýNöC»€~¾'Dÿè$Ýñ‘r &VÛ† øIë4E;'B:À Ê‹¼¾ø¾Ém‚âH|E.¬ÖTŠ9÷$=r¾%+ÅÍ¿¿;ÈaØy¶Õé©cÃÿúBÖ \öøªgQýÌßÍñŸ¡˜´e»š=šàcpZe“önGB„aºš«ÑE[V§ V Î}OåQ”±¿Q;‰„n¼yarƒX˜6r æÖ@Û1G;=Úîæ"Ú²²²hëVqÙiM…¯ P/€c¢Ú)J^½@X\6%s1¿=$^i†ýäÐîè!±-<Û_?œÖf¬cbù‚4ØìûœÊ-îÉ¿À¯¢H›áoÆzüã.ì}÷}”™H`µ—ÅÀ;èe¡–ÏÖ\K‹ã¦áê–‹ýÄÞ;“‚ú.U¸×Iƺֺ—I¼œgàš¯²žÓWüq>|ßx»­ãΪÞÚܤÏíùXY+:âÅxYôeÁé ¤Ã¥œ ~ùìõ@4з|^–%ÇnAD•¸Ùrý‚óÔ©Š½­²|ÀaÉðî˜'ç0…kkmù`8£z 0¸@Fš"»?4£Vy?`uÔ·ß ßæÑë¦5ƒ4}”Á@è7äÆðkò4X"îÜÍËü\‘®c¶¬jǦºÁÅUíÞ=§-æ­K"æÎãÔqÓ!AIåãÄìªÜU­1{idSeÐC í÷ Èj>ÚÜÕYL$%‰`L>®º ”í«Uö)š¬X-ïî@\@ÙSNÄ ×ìJôÈÌÂÒÞkøŠ|[gl »ä˜7è´Ž’lÖS¢j‘vR\âUÕË5è÷÷°ÅE \‚~Ëç¢$âë×Ëz2ÆØì3m¹{£“rf‘©Xš3ÒÀø„þmå•FîY¡?dVgñÁK…ý/~tó;6TgÕꬸʼXKÛ~¾oÉVgá# Ñ6†rºäZAnƒp½ÝJ»DÎ¬Ý üôÔüM[LÌfs9 ŒìÈ2´@ú<°)Ö‚Mó,ÏÕ¿UkÁ¤HÌ.›ûeúÕ2˜IgX Œi)û™¼a¿+`IÐS |çì[^½ù«*«×zÆu&âÿÈãFº*Èõ¿/D9Ì-\ZEßò è‘è~âtïÎ%ÐA^j ÎÁßëôTÑílÞrµµÅ6ö_)ÚÔ,U) cÀ£­¨‰TXi gû‚ ;\h»¨ˆü ø1´©û(OO¦o’%b•,jt¥£ €œk|²1á\Z¸6X<Úõ7–mœ;|t ÇH#üÛ€’íóÇJ ™N}Ô£œcTÇA—à§M¥å‡Ž‹ˆ¤‘à+êÎZ·V¬y¥pgÃã$[ÖíÝæŽLYªÇ <ñhûМ†PJäþ¡'¾ª“Çu¹ EÝ>¹ðÑQ꟟ë*µÅ:[4îRLŽŒP;æJ$Ä5àF¶eÖÆ–ž8šž¾*ý˜æ6eD°…C¿»rHMI»¤{ %óÌøK ʾÛ/KÎ_þèÖD–`le}å…ô‚5Þ_¿è*}8…GÓ¨ZsôòðƒÀpÅÑиá þ.¯‹\/,Ž¡Yÿù[»F ³ú“þ¦ÿ¾p®†YZÁyÉ\'úïU¾¿rpx.É@ÅÈ6´Ò‹%œ^.iü"$öÚûÌ'Y3škÿCÛäÈ{5;a¦E¦>åiSmKjÜÍ¿–9GáŽÀåüÒÊ\Û-á?oœ~ï­Ìöu`-¹¿éÜ+jx¼Pˆ‘Ün Û”Ò~0Ïïó`ª—$³#®ÿ ôôš˜Âèž@)8½¦dú´Û¿*‡\D¯Îð!º5JôÛƒsüe¸™÷™Á4[üœXsüšzqà T.Ÿ‰˜ZKœcÝ’AáA­g™^Aðºêõ^Ê:ŠZ~ PÃ’” °n3JrûŒ<‘ý 2·„½.ôïN+{ }¤¡]EÆÛ.R*9©®­˜bÿÉÔ/ÖÊW´ë]—Þ1lÓØ,¯¯}!Ë#ae¿Žõ¬>ak«i/S\OáähöT_±¡Žu[ðÚPi]9Eì(îÅü´,`‚Y¾S!_´4HCõ[«"C V#læê‹ç§Ðw¹¸CtÙÅË:pBd„ ìâG9á~ˆÊÒW×7à ûžKg6…(ý÷]HQð¦ Jû3ÿ‰1¨þÙ3„i èÝĪáïáqü*¶Àz' ðÀÌ6Œ‹]ÃÍ Ó`Vxºt®×Öÿ|í[ëJ £+qлvÚìò£ò™Óºt‹gZ¸ã.ÍÛ?7B. Ÿ&&Õ~ÆW䰼܉(†r¬Â­m°HÐU”n˰àÐSÍïHê ]Õ–¸šŽ¦T“‰ÕÈ ZáýšŒüâ~«N~´%õÂ)ÜÏEö„NŒÒ±w9="ëCÜäN\ÙµÃ/¸i¡'é`6mŒ£’äû#e!Ý òMûò“ZÍ ¿î“Z)¿1{&Ì}uÅ;á ¸ ¡Pj&Æ-ãT\ÕYb"Ó˜¼†¶†¹ÞR³8ÈÎÒçµ÷f-²9šãÌtzlàªæžvÊ=[)~b#U dÓûÓ¦‰4.ÀÎÇ:²D3zËØÓùTï x¸¤i}¾ª¶œæ…`àÐ;à|,6`ÊìQBäûÝ+\í¬)¹* —"¥X¤œ`G^Ô‚^ÖîãæUG¦7QèT†ôH|£4§¦Ù‚¨!ÔÜê1fÿ@©(»9oúpVMÇ‹tr=} ‘Cä)б@r‘A_ùAáXH,þáêéÚeíaÕý˜mðÓK.a¨¦|^€ŒtäѺ¦ìpKk©Ni¬+”úQOç•/š|åÆ2n^3â?Vï’²] #Kp¯\x„;+›B±Û™84›íÙˆÊ&(_Ø/XQ•§î¼²é| ÷)ÖWƒz*›G[Ù¼á +P£žB‰ohìÆa#_h¹Œù}ªn¶ª£RÔ…ô cýÐÙ… ë·Sã±Âî ôêÄþûu}`mFH³xsŽ”kÞä@||+‘(B€@˜ ѧk‚-îJK %¾j³8í·¯ÞÂ%ª^¦Mž$Ö.Iúõ”ÞÔÏò[N`‡}ýÌVœo•µ§œL$œê“ÚöÊœŽã 8Mòn)?¸í/©Ä´·Î{ÄG­]+‹öãY šÝ¶ ÏØ¦b#U¦©éoɲúuEȶ‰ÀËvlWbÉ•@E ¸†ùκ}ëB0ÜÛñ2¶zz¼ˆµ…sœFMÜF ãÀBÁ’Å®„'ì̱ªè¨qŠ¥ˆ‡¬˜Èü·¾èÊ©s8‹ßë·ü‡ýRçÍÓÕ>àŸW”"–f‰Ü—¯ <éJï„e@rC/g=£ºõ¹?–¯_@+pÅÑ0(ÔmvN’B2Û°GŸÝ.uú$ë2²‘óå´6Óù44õ›ÉØý÷æ©áà«\’ã›3ÞGóAú®ü“WÅÈÆöx’êz#&ˆ©x3D/j×+ 5°>àå¹{Ì„n=Tò0õ þ¾mëT¸©àKwuùoÈDŽGɾÏBœlœêIˆCÄÉо“ù+é7~yÆx"ª™¿ÏJù7‡$/vÑ'áöÃ’×ù3ÿdö…Zá˜Ø$ì®—Ž#dèìkÃ9‹‹âÁe® e s'±^÷a+çÛÙyåK2ĸå\7o:÷ïG&m»b…? ‚Eæ¿…Ó*Ш@›ÉrBæýe”v½|OœKfko|iÜÒ`HîOm7®IrnuþB…$²¼| ÷˜Õp·øèé3*[_jØh¯¦.’ŸR‡Ù.†Ð²%8³áÛtP{¶ÌgVKèÐøƒpÀ›Úwû%btLË ”ó¶Ž«jdó¼P ­:mgTÆ<œFÿ†Q¦IL@±ÛL^‡djw³d‹—¢°’$Ùm_umý(\Ù·½YÉÅš·c„G„;2¸µlç'£ªæ ¹ÌÐâ.ì ù€–®,DÁcÓÞe韚„0°‹}|­fTôûG¯=qø¿¼:ˆP¨‰ít5í´Ð÷ #2aóóüŸÐ°' °4 ^ÇÚw¾µ ï[‡j¢'+EŸo`¥N¦&Þ©>¼ Ó¿mØíû¨ ËxêU9ýQƒ¼TÔ(?n?δæÒÒÁÄ“®`™‚cäEô6µœ…ɉ$á\mPŸÝkª¨àºØÜßµwÀb43÷ΘéŸÞh‰¥èqÐŽT¶äŒsZ0.¥_m.Î)¬ÁD[%=wŒ1!(sÙ=Ž€gR[Éw ݗߺ8¼lž{ˆ½I4f;°Ò_)–Xæxc"O0‡˜,k=ôîäç½YŽYôåg°¿µ$ â¢T¬·œ^”Þg'<¢×¬ãw8YžÑ¶V÷Óï1ë᥈ÙuÔüiøfOÏ!ð–öR”ót]¿GåŽù™Èý`44(GrêZÁû`Z[*߯œJ³pÀ:)·M³Nã!aâbLÉc¤oˆN€Cª–›t0 \†û´„ô|E ›š#«‘˜Ð™N¥ðÕ2øk¹½¾ã€hֆȹOb² êIOb[\b0\“އrk\AuN?n$u¹z|t?Ý÷Vé¯÷~‚íåéÄé§4èT‡ÑßA1\, m¤ƒÌÓ™ÉÓl@Nž‹ëÓrÛ ¦ñ6ØÀªÒ 3»;Ï ˜¨¦f oß’ñy¹ £R2—JéÙ˺ÁñPߪ'$pn 9N@“ä¢ëóí³&þ,(<”Fèø}µ"ŒÒ›>žžRPÝÍôºÿ¢Æ¤éoßåzÍðÚ.>_ìnPĦq»7¶(|Iƒqºüü¬eÈ”ElÝ„'³¨Ùù-^â|Û]MKj6 }ØMRö?ΙâÏ€#ñDó8ÓS3²!¥CgBî $06çÉG@…6˨ÖQèMyŠ ™XŒã‘( ¬ç›>ªM=níÇb=ièäk1–sèÖë^ï×â{«ÄO=•¯Ušü+p ùÄ=ã>¿,õ¹fûÆê ‰–t\ËÀ³_D ™|çìøSçfñdÛÀîm¤›£qrG:µ›m¦~ߦC4ãéhë" ë„÷ÛåÜ\¢g~ÂŽP +"ì‰Huºp×Ãðÿâù‚ÜìuT þ„PQÏÛÆ-ý¨'›kYûxÚR¾¯×aÃK’¬AÃ:c½ñXÂùž¢þ÷ÐX«ÂØ]_1ÁzN:txT a&¶M}ÿ‡m™’&A‹(K—3«GÔ¿×ó®ê¥§ßdòÉ-×òÔ5þ¨¾°@rôª!J-eÕP¥m"õ!^´Ÿ÷é´ç|XXŠÙ¢Ó`MìšÛâúä>ÞíŸÌv]|ÒÌ I-Ãl²«—ZÍÛ^dÑ(#äÊïÿG¸Ž8õŠ u÷8œ-íò:¿ZN´f‡$̨QbL‚‚R»\’¨ÖÔÞ£¾)c_u2¬=D›¯lBW¼‰”Ê‹8HN¯Þ-¿9*¶SL¡Ç؃ZöœN«$„P‹}6î›U†^Z<°A…ÒJycØ€î12äÌú¥ƒj30“¨W ŠÔRfS\ ]鑳ïg®ŒÝj:Ð¥ÞVÍNš ºÂ1eVÑÎPZ52iœº²Qñ¢DØ(“Þ=—EÍŠö‰Áa–%2/Nÿ²r¢ jûF|¬ ^ßÍ’[˜Ì+pü×n€80³¢دñ‡Œk¾Ùú¿úýÓÿ¦t•¢…˜RnëW†;ÚEÌk&i‚ùKÕ¯ÚöuÜàNOž^‡O;ê•2êdPöͶ^.é0%<Æq’‘ý«tSy)û¬í—xîÅð5²®U'ÿÄ 7PmA[%ë%uSI$DݡȚBJ¿^èÚ·!Ö§j¸+‚êóVAàvÛköC,i]`·).±1tݪJsÆI•eã߯àÍçþç³óó8pd™‡ÁdÚ"ý½Fæ õÑ:ÞÒPü¸j<6Á&³Õ9SÕÑPˆÈ â§ÛÔ° ¬÷P²|“àðFÒŒHb¾[ÛI^w_Ôör¦²» …ÿÍD²U˜@«6.±L†æöðr¡šõêå’Ê)éeŠˆNŒôŸÍ“A?â½Ò™·AÔ/˜Ëz¢Q_*ÄÎÞœ¬Ó0å?]]3ó%CÄ䟖w¬ÙìüÙŒ õòÚ-’·:èÄ{!•vµE]Þý9 ÝøåF®ø·- 0=uZdËŠ¡E™|^°CLëø2éš<’Í@¬?|)q“§³Jø¤V_ýàΜ* ëÄ®~0Žàp1 #Àw­|"‘)û¤eZB-k[¨Dñ_†:  z–p°Hn÷Ñ~ÜaÝ4åºJ)©4Pjš[›`çO!†ô<‰è¸½˜™Øæ, ÎÎ¥LE…ôÿ—å7éÐߢl†ŽsÛ"¶xÝ·¸PÐ!Áܯ0°2 v;Ð#Þi:(OùÌpA¾à¨<•º>ª¢“ô´êqdï¬ÊТŒõßÿ©ò‡¤PØfc˜mUæ4áÛÂê² !†ŒTÎê*H´D§U2ù Rº¬™§‘Ó†î1ìü9`ùô}×ðBé} DßÉõý¤ç&R‰á3 QF6h¶¥±_=ë’øRîiDç4èó!©Iô^ïqæÛîVí»©¥‚õ{ùT¾|ˆ $)ö ÝÔ4%]B ÌÑ8:ØßpˆK:s²câeÌÒÒ*K%„D#…Á«\?{GFØ-û7É€–:¬y6EJÛ6]ÛŠUs*ྔ©˜nÌùêbé¸a:~㕇“pg~:€ÿóe.—G÷íš©f¥Ÿr¦\g”{7 4± tˆs•ËÐÃà3WSÿÒVGÂÌ«ÎDm3…²jŽkŒÖ6ef¦ÕÚ¹­á¼8–¥´Ëf®%O¥Œêl|®²˜. .y™˜¾!„ïr|òÑ@{÷¤ %º ±8Ú–øÚ••٢ǞÿÒ«x(ßo+;>h.᜸,m£dïCtN‹v­³Gœža¸e}Z2³k ѹòç3/´²ÔêÔ! ÐzLÈÿp}ÑDÆ]ûȇj­Yînˆõ—>ÁSÙÈ×ç9ê`vFn|Ó¢æøŸî¦r$½„âtÂAsùedF¾>õžSä€D«Sa·î¨1RxÓtt8ш(ö¶8Ú°éÑíê#Œn&Ì ÌªÏƒº€e¹B‰‹°éÊ^_Á“ó,>DSHq܇ ‰ ±Ø!9eµdJi'=0 o%Þ(ríìØû¦ÝÌ^¦ÿÙ½f1]')~΋ÈìåéŠ7b.72ŸkÅÝÐyn¿4ƒR˜‡`yY¸1¦¿nøI <æ]Y†5Ø©;ÝtCÐÏPú-ÚDä§°Ú˜™•ÂOÒåvmÿ¼°1¿7?[!G¸—ö›ñ,k&ퟠ6ßo›Ü^ýNxbA„ô÷6i{ƸqÖ~Ñ>ssÃ¥²÷¥T hûŸ©{ì8Æ“Îç!(D7 iV`iKL =öãJyË73²Sô}¦Nü0«Á_K“zø-‡uÇ1cϵ˅ÅkxÛ;BQFÅ:`ý¡y‚æÞÛÄ^CÕü¸‚(«˜wøŠ˜•ˆé –{´5ºíÀŠš÷ÏËê‡]¸|‰ ‹I—%K´[™~¿:uç‘£Ýd•$FÁ{A ypw·ÑH‡ê ï=F¾;=EÉ?~ ò­‰½²æM¯Âöûûé?ÅAžˆÀÅIœ‡ß£Ç¿Ú¦_#‡-B”ƒŠÄÆg'×X~9ïjhãí³|]äñ ÈJ.ºK´'Bãòj=iv×®!Ï¡¬ -Gâ€âP;Á‡úN'€C¢±>ª|ÁRt6Suò´¹€ÿí Æë,=È¥„+J¸FŒ%ÉPÞ*Ír'·ÈzÃP'ãë<ü€©~`#XH‚/G‚œpþªÞ†¢‰À%ÑC$ªkÖnª9§ýhs¦º·f,…w,ß=$ZßnF¿=Ö麙 ©@êô±ˆî”µö©mL,»sDcÀÿa“a³~$ü>ßIAˆ"›º{xŸ_´òÇ}Cƒ¥ä¶¥‡Œ,È<š*V«dL У×ÔÔ,Óµe.H½wv=®^th†p=}gZØì'$‹l:0×Þ2¤OÀ,XQQŠ O'ÎuŽþ…‘þè ­w1¥ ªHÄÒE˜u±²ŸmZ|æ—å‡D‡Jh{  Aï\$‡~ÞDЬŠ¿3Š‚²P›«I' °dîX†óÓOZiæÀd#厉ƒñ¯2˜Ý~ &Ç÷BVÆm¢ÂÆþh‡íã“‚:×sWÍš qÝ.¤k|ŽeÒƒ[Þ )ÃÚâ€V0NÁwe$ݳcm5÷T¶–]·ûݰr£:à8tDÊ õ,®&£ô'pï‡l2YÛ-g+ ]HÃ[/3…&`ÔˆîªR¶„8'¦ðçà&¢É8V=gkûc&|÷Ó2šÉJ–íì?œF,ÞÇ6­Ó¬µ¯e‹ØKâºô¶!¹ñOá Z7½ÞE•¶~ bÃ1þÈ¡èâBü_Ýa73éòVÊýk")£Uÿ³ªøaXL^“\‹ NÌ£Lûèéâ87ÚåËùD¨.7üÑ‚(ŠslÌûL\éLPµüМ˜Ö øÓ%Œì¾8ûÈ}ÍÅÉö–xBØÇüžo–4þx$zaø8Ã¥1”|OUD¦XˆÁ&›!†ÃzmO,r ÛÛê†u3Bäÿ—ãj®XY<¸”ɼ2uƒa»KízÚËTüÌ‹­ãX:ˆqúkp/õF©rã³]Ø(j Ï—ó\ChÙÇtJñßtËM¥>_9†©Úy]ì2>Æe Wg§@!•šP “Ø÷Ðц¸a0Ú`U¼a Î×$A‹yÉþ]1ë 8¥ 6µÓ0¬=¥1UÏ0º¯´I¡é±•$«¿qlYÖ«¤­K²¬Õ mÉÕdƒ@2m:jZÇZÐûÆ`KL?ýë­Îy³Vv·C¦*ée7i~Kí'>n$—|š² óS®ÄÈïñÃû‹ÎvŒŠÝšzzø¢ðæA õ7i©CÛÁq–çgaýÖULíQys˜ö¯C7­ÒzŠß¸[PÓeT3YÈ^ÁÐ1(j®ü’ÅX³ï†Ö¸Û¬³¦l\ð†Ï"“:¥t`‰Ü²ŒÚínKÑš$cuT0B?­ZÄ¿3¦¹j-e¿ºáVáýM–åÛ@e|Ü…M>o;òÁ÷œ¦8³Ë™sâ$êo*÷@Î*£•Xâ*ÂðXÜBΫ7îð®&תÿegª•›ŸPÍÎÜÑ´~æ™|–XÿÝL¿¡Êr81ĉøÐ²á»¶GÒ,ÐF8‚o1ñ3,¼3læ3â=G|æö*@éâüÝÖˆUN‡‘*R€äÔ ž!j³*2y?Í€CøH ‡xÌôsckm—ç%G¼­°¶vGš?虌åºÑ3€s *ˆ«#P3âB(å˜;ëáüv¹1m¡³"‘oŸ7"§,ÐM]ìþhÊMä# Âë ð0Pé|—CSV˜á>T6SXUXñì ¢aqkæâÐ>´ ‹¼e4õù8Ö³I}±TK2îvÓа” Ô3H¢5-îCŽWªÔz•ïéî9Æè›ÙºñJ÷Ú)öÂìO$;¨[²,…¤š¥d¿è{xU$ÁeÓJ¤P[Ýa’ U7° n¨éá=Ceb˜~‘¢~ûZŠE…[ëÖ‰1©¦ ”ÝY!.wƒ<\ÆÔh"Km¥‰Š —+c0,Z Ë>Æ©ÝæeæƯJ€ÅóHMá뵈h=Ôûå©GCžeŒ4xØì7î®áªúâñuÚYŒt㯃’éÎBËþ=;)9Pç6({pÕÏ=ñޝ[¼òäï)ÃúÑé †žŽ¨>8“!çÁ”ä‚c·˜èÿ iÆ=X¢+3q<¥ í£fº¶vä¨ü,÷{‡™+ê7úغå~?¬“Å#fOÉZÉ£O‹5ñs­¿Mägh“û3~bzŒfø®RÂ( ÔÜÐ$Æͤ  ”Ü=¼O¬ãìÝ>‘üD¨,£ü™»ÃOÒJÅÓÚÅ{žéèQÈVùËX_Ú8ñ má(î `— Ì ä!cn¥_6BÞßâÔØ¾L&4øÁç&œ%ºûÈÆ°»¡UPøiŒäõà¨ûkOË>gäR¥cÝ ÉÛª°9¤4éB‚%À„?> ý Y¨Ä;_,}¹Œgãÿë8ëåm0Žï LÊÈ·›1üHœT.ŠÚŒÂñs‹wqBSÚý ‚þ ïÌõ(—øCõ_%`Ê&Ù™£*dB™´Åèl°c9#µûV°ö‰ñ¶o1I½8ìß­Œ>`u1Ðt²$™¨yèmD‰ZÕªKÎ_¥Ø‚ Æ ÉLgãWÿo›>M7µ¾û ›öhéÁëåß~ˆF“‹E"y,ÄSçYÃŒ[µ è®óé¬kÔ©A×gµ}õ·š=e¨Î áöü¸ºÙJí•éRTÉB­®ÇLëܽ}JÖjyr~ÅÝë¶hãî 7÷êcýùþѶ÷³4é$Ú½®§ˆ¿›—TVnJNñ“ú­ ›ïÖ^?ÍNb›¯NÀ"ª>£ê7Ï;¶¸Y·ƒüÜnRû"6dØÝ»²„-Ž s¼;Òþ´áZ-·ðéͬ¸Ûûžú€:îq½Î=±†Ë_ô\µž8ù¹”­ÞZF9q_—žš&ózÁ®‘úV6cäɶóÌï±Y»SËå%×3ÑÓe"$ö[ÎêþI[qšƒ#Ÿ 4Yõ¢‰Å÷šyÚd˜f¡z„lçNB8'k³_¤s5].Ir]ïòDv@D7Ú4tÆ/Ãf{:åè ®Z¥À•<ÒÈ®&h½›œ å*Ì؈%éq­ÚѰZˆFf¡ÛŒ3^9‹×›AŽ‹fOYÛ¶ÈâaÅQo&Ì,?°r݈4ˆÓSQ7äæDiƒÁœVÖ™Ï2ÄŸÜL&ˆvaJ-ˆi·¼¬˜ 2(¦¾0Pë¡®JD焬Üi†ÊïdÂò5¹#îÞ‹°;¸Âޱ$€4~pk(íCÖ¬)ˆXð|^ó6Óªà­Ê޲P»G©fFƒ–]=hð¿ìÓ­¥\mÀY;D®ž7õ‘ÀÉ<¶x©_o°Â)­ŸGªå_¤5Q¶» ,7üfE.ßäàˆX·Šú3½jJ¢h`ãd)Û¦a/19† ô÷ºw¸®Þ>v>«Ñ¥œ½õ3°„ï•­xÙ×ÛþÒô±’ÏA†¥Ÿ=ùa⸠ ¾¥?ÿß_uŒ>»ö¼ iô£Ã(R(ƒ%7ÆŒªdA9½„¸3÷ÀmÇÏ&‚&i¹Ü•‚:Æ'»n-ïÛ ¦ É—ÒL¸àLº7º1<>UÉ â 8’Íî°îsÚQo¬Ôi}õkj×GçB¦0{ìúÍ5¢àñ‚GŸ+neÅë(ðqP&Kò¯&Âò¿ã¯–ÿZs3/ÊÀ]…ñðÓzxæ—(W¡ñìzkDðæ˜•>¸äèºøeáµø¬ I‹p°ýoñH®dEMh ð>îÑp4Yiays鑲dž˜*µ²L8}3Ó¬àŽŠ¦)@‘GLéȳAJ•„Š<´°9Vù˜BJ…íhÒàå†V³ÜæÁ·ŽñO»â¶pt ÑëÐuB(_[ý¾-Ý>¢tzIÉFÌ\ªB†ä}Œºù÷4ó&7æ¥Ýê9XAÚíÑ”ñ"AstÙçØÑüã:5(„k³¾ 3ÉJª§ýƒnér¦’ü àïÖÇÔ¨mû»²ÚÑôÃK +ò=&Ñf· pb©9A¢ ^ÑÈ¥sPvw³ÎŒàf×6Ô"]BEWHƒ@›jATMHa‘åRt]`¯bÔqï"p —õ2òAÇñ¡‚‘µ'ÕʵV WÜ€Ä@ù*tSÌÍtýÁåQr¸†zÐx¬ÍwÖŒ’&‰µ[ܻӶ[ÒÙàe-èš=wWúÕ’Û¯«yºñ oé`‰Æ Õk²Í¶\Ðu辶ì#AÛÔ½n€ôÚì×µ®–"niœ*Å n'ic/ã~ÉáÖª S±‹Ð1)Ø&HœŒÖ½a ÷WеÚ4Ñ/£Ž£è웣ÁÀOHúœw£ío‡j-®|è„þZQçõ¢|A’­6‹èh<7‘9Mí¨½’](ÀŽd¸XR ™K„Jˆ=…²8ͺy{̾À.í*A_c*ÙuôFã«j‡Tå{®GÜomãHá¯N[³øý½-n$ÅÅ\D@RhOšx›ŽúõÇGÆ c/àøô£éMaxmýÁ¢—GH’Z{‘¡%²Q‘°K¸Óz§iN "±À—åyI|^I@ÊÅÜ€I¦V`¯Tqõ·™¤: ð\êe…£tÅ60_Ÿ ;¡kgÚ‡çbÛB‡54B:­Ô⓪€(¼ïyYt¸et dwŸ®ŽØm]*VWù6‚J”´~Q.ÁI”—ËJôu3Ú•hzÊ5ÎÂjë­&ë‘+3ÓjàãaÖZ†Û0óâx»"_5b%/¬Þãƒ4ó‡´„d€IÓe­F¢‡ÀÕSðPþFU(:È.½zø8¢†…ì¤ò©tÀÑv¯ü¹µ-sòËÁ'$ ~·LÚÐåNûi7JO7ž1ñ“oÝjîq¡hÓt÷¢c~êGu¨ƒ´¦°¢;‚`†ÖOT¸¬aUÊ?I Ë+ôÀ˜cVÌ 'ê`‘5?‘Ú¬) )ÄÈl–ä¡ÑZ8 -ý™y©aqªUƒØ®[ȤsŽ"û%Gz7Yª›uE*w~¡Sˆ dà¬!xŦÂÞNx°Â4}<$•m9D} 2íQ úÒ¨oû%Öñ-Ó°K/n£.M˜ Ð…€‡G_³”ħ§œØ_I” Î»"v9v©'\Öðè+àû”©‡¢àÁMÊäÖSm*TI y©Ê²¢üAtQN îCîÖÔ›fíTÉŽÓÉ·5q«–œY%vÃì‰ fœõ„òî„!·t6Ärloé²C~`f×ùþœIjá8ó¦Õ¤v|‹„½0V«ƨùó?Hgä10Œr¿iÐè£åÅ¢%²w¾²Ðº5N„ÏO C• ŸNu¯7Ãum†}k7³ ßR›°uŸë•p6‘Xñåï»ÞK ½Ýé ¸ì‹†“GKsYh6J½ÑŠÅƒ²ò´A3ý=a5ë5X{–h†È]é— ŠsÊ *_)±v4% ¦k÷«íoYû0ͼ… +*‘ìI¡·SàÈÖ(Ø—Ü žAû…Äc‹dà?1È •†BxI» Ì·ùµö4‡zDœ·óƒGv½øé-Š÷ε|CYHgºì WÝ@œë-_÷Àõ Àï‚ô"óBzi¦Œþ>™š~avjç÷+RÑ¢YY …õÙµ4<òIvKhÁ[ù´øyh*IíI m˜JL¸V,ʃLJAUïv ‡ËÿŒß,3Fç,«Õ”³#ž 8ªzíN>ÛXŽ÷.:íÛ8Yåºÿÿ7òÿˆO2v¸#3>|€H)}ldÂxêA¢¬ÍœõG4'竆q|!> "öO2Cî`¶z¹ßÆ Bul·ëâ)”ýcÌCǸ\ 3`¸²Uè4zî¦?- tOÙ#¯ «yDGÓ¡ÎV7»²gHÂ+ý¦ÿÁ¶ÐL #‚åžÙAØÅ©ÃZLK—Wã¤g‰`1¤›”9@¥dBozX`xƒý¤•s¨œèØÈP [ËìœÄ„â8Y;ã›íC±¢LRrVè]üžGèdp¬ ¡á¼r¥þXô—NŒ–d'%ùzx…”µ#X¸¦µ`¥ð²ÕüKù¥h³™Š=»U$Ü€¥A(  "x bµ~v×ÿù#Úª¦_˜ËݲJ :äÛ;º¶G¾÷ˆqë¨~È(ýo$~qèE)Îõ¶Ó›Ü‰ÛÒ—Ô”ÓG^Fµ…»žŽô”yKñ3ÖãªXÒŽÁvóPŸê‡6•@i¾p~¬êÖÙG;Ã˲*¦ÃA°Aèqš§œ3ª~Òâº](V†güÆ)+ô9™ß;ÎKEö›ççÄ]Ý_ô¢Ypl€gããˆé¿e|ž†»½è«ºc=\& •Ðoop/æJOn‡IüQÊ-Òü–¢¬d×òú¶B‹‘É"¢œCžÁÅšòE+—˜_ßՈ뷖ªˆ¶ãÚp˜¢>äÇ=7fÄŽLØp~ó·m¼Ãƒœp¹\Ì[5ç ¶³¨ÁÇT'V úÁƒGÕ>sèeŽZá6ÈØ ¨©¹AM£`˜—0Zí"„Z!ÅIxÞý ¦>…÷^]àÉÉ«šn”QÜ[à@½(iÒ&d®ê¢ç õ6wß´ZÑöê§Pøh|^à¬L/­vB lŽ*‹©ñ¢$ÛPx ?N{ÉÃmå¿~4rEün- éqiã)qtmùJ3và¹õ¿^àG¸¾™Ù&‡¸þ#-^ÙÒñpž£&ÂvüÆLa£<’zÝyž­2%¥_ì3wÕ-!J1}–”AÍ¿ ÎgF$µ=ÑJÄ8—æOXÕºìVÂ6ZÍ{*pC1`ì7"¢­,9ïï‘pÏÿE[£kU °ÎXM ÓCtt ØŠ@E¡êiRLÆ…1Ó¤¸OŸÞk;DS{çÔi\`zò»]ãÖ¦/y: y@?Âéôq‰‹·ùNJ-õˆº‘7YÅs@ë»ÌŸσ:’)qp«ÁÓ/þL`,'øñÅÄ4Ù‹°˜ñpQÏÃó‰“ù>~ƒ(¯VÄíý‹õ.ñ‘ÇïvB ,³…œû¢lôûhaØom…#ÁÆÍTŸÌ~$…¸65“ïiaÒË/Êq „$Ùû.LJÀ);Ô,Â`úHºôjå¦ÃA‚ïJT„Däò4p'ŒÉö‚î]õ¦éÅ2QÚXAŸî.RZÅÖÐßdw’“BÄßÑ• ¾å 'A4‘ÃG‡y+•9Â’Ó.¥Œ¡( ßçÐkïfRº g"§…¡jÎ©Š )ûrÔ-®§ëø]BÕ÷_±èi†U—?`Ú÷–):ߡ鈣bçk«–ŒÛ®KÄ ú=zÒöá…–4ßO_Þ¯Vhó{ì¶ÅZÔ÷B«ã+šoÓU“6#µÂ¦úY þ¸:E6Ï{ªÃgOe¦±w€Í¸uÝ®÷º,K«8àî!Ÿ+ý+ô.ñ’·/™Óuš¼ÁÕ?ÿ]®)§×àü4”Í?Æ Î™>Þ¯@«q)Ú,‚㺂;K™ô¦,Q§&Eº¾xö„€ÐÐeúzí aããSdrÔqÄ€÷ʨ/·Å bÆÒžõ‰_µ-–Ã&ø× ­æBêv9G%ŸétmJ¬ºÊ×ù«›U¯FYD”_™Z7¿ªí׌Ù{7·ìºG^ ¤ñ‚ K0†(:ÿ}èF!R’’œé—p ï£+Ï—ÛìNi¨(wFØ׳5嵸 g\ü¾Hªÿâb ?ÃÞ»0ÖBL°3º…ƒØGLìÂþ«¿A>XiËÜÓô’Iâ9€N¸:wX©1ß×@–7y\lš…3kxxdïـ܌ 9§BGdÙdtñ|ç:Äi(¹“#‘ÄTë¹¢ªB ØJWÁö JrÌÉѺû{Œ öÇ1ð±ÕÁÒ)§u]:z¹²€5s‚c–¯×un l¯ßœéç"/ðí°ºIÉ|ÜÏè ›ç²BãeKÇ[Œ*Ú5³Ñdš’@§}Üjæ*}2ŸðwW]¥ÝÝähj7•b‰5«M€ÛÜ “J‚ÇUJÿzb{ ¼·!ÝmÚî”ÞàqÔWîÝäçe Ž¢Oü·iö!NkäöK¾"i ½rÔ²uÉ${¥c¼H3'|_AkÛ¼':@ò gòT¯œ9ÖLNhåú¦ÑÌX-<¨ÊàQâʇ²®#ÉMÓj»Ÿ-ijù44‹U$«òlÂGåzæf6› Øã•ÑôPÎùÑìü³Éëî™NL- !6t`UM˜Ê© œïKÚŸÐÌ{à_‚w¼vÞeméÃc5' ¹±åì MK{… GôÂzll —V_ 喎Ĺ ‹¥6&( tµªâY ËödQø7;+·÷+ÙÍU™ä6‹‡±ÓZ"`ž€“ô%ûäœD„*°`Ýjƒ9i3sÞÿ å6©HЇçŒð›ÓMD”Ux^Ñ £[`«0ƒ¯‘iÃäó2ü9ÏàÜ5T‚AýIÔ›Ï@’†cï½!ã¹MYœAª­ Ëö°§ºs ljȷ:¼‘úþÇ:‡"¿©qèz’!X Ìà|ÀšJx×¼-FÝë @¦¦´À>EŸEtfÁ¡Öï8ž¢²T$89ÃA©¬îA‹õü ~ù• £g¶ß¾ž}½íB•àkPïElÿIKð[ÖÊÁÅSÊ?+{ȇ­Æ»Ö ¤JÆÆôšòövÅ4v"öºRõ9&±|úN³}†¼kû'°ÿ8È) 5­±§ž4Fñ¸ŽºB—Y“æ»ðüýRI Òãç°¾·œ©íï¸ô£šÌ·O¥PM{þ|óZ߯PŽÕd +S‡ J“¦t>ý(#µ®¯‰ÒG\Ü*ß×ugÅ}ØI0x^Ô¨õ„¤ó6"2¾‰ù¶_â#K$ ±„àêÕq²‹ÁFºXý‰SpOtÄ‹…Cè¥ð¢åýŒNZKù@÷¿j@16ßÄ´^„6]>“'ñ€¯ç‡CÉ}óãp‡†•†¾|ÅÛ™£À°òQkxHàùÊ Ž¸ªõðóXùŠ dO‘ù[¦*|iÒ B9Œç¾L‚ôbØd¦ê4mRýUoD}‚6ô[šFÍõjçC8Fã\œÐ øƒÓq¯JN‰:<ÑôB—¶Ã1烙R4îGSáh¾=d~|zö®µ¿H >ÜÛzÿ†ûaøÃDr^3Ÿ Cað¡BŽY‰X/2äÉþ)ÖmÓ òÎW7ì3½èY3Ç6 5„û€™HÙK»^Ä«·“=ÃÃûÆ×±¥´dt&Þýèм4ødZrìþà™7Vtw(ñ®*ÈàØæ4ÈZk ó½xïÔtáçy¹J$ÅhÞåÒ<`)ä5ÇpÀÔ‰ý¯¹Æ5ÿEÂI~ÔžHÞà*žˆØRvËÜÞH"û=›ÊD.%àš÷€¶;û“FýÅt?¾ƒ¬ÅTì?Ó(ô0@H¦MAî³û—PÆŸ xe`u¬íä °ûìe݃ÛS ü„U%~©4ß{ku[Ùaë3úþ¦¬á4u5ð>¨ÈÈí |Cƒší÷>î ñ“8ï.Qäe¥.GÒéšFr_?ïÞv\Gt< ÏDs}1­NëEñÅ™JjÆÜø°Eä§·’`1Î$ê~Û¿w4½ÕÙ.‡½™¾ÇÍ€Œ«÷ÍÉ•Üàѱß‘ •öÒ¾æÔšúsî°Þ×®áetÕ²|tNðØ?UÒÃ*:Ê/Û8ø¾!2-G×&:›žŠp(g7‹ø9Ä3R?výäÔ¸YÑz ÑRçµlˆ©ôÎûôoLìN‘7h,Y~~ê Î.¹üMÐŒ‚U@¯#ú와s͆‹…ÆõdAØt¶BtV–WÌ;¦Æ©·Ã;=c‚zS7•(‰–¡«Ùv–TNMEÿÂK%3Æ/£eõ (‰pÒû¯ê¾™oŒšæÚV²ÀñNYÁLËÔUJG§µ¤‹ö{çÎ!Ëa+ ¤çÈ=¸B§gƒG®íÒÇwó/Øó+ ^˜zb5¹jj›âî?:ÉR«¡çKšØº×»‘Fɦ›]¶Ê!ÜÂа6õÙ±>ˆ[êѱƠkòµº/N®³À© ¡;“øõ-Á#­"JÆ ­Yk»H’&cʆ8Ty &Dh¤­â×¼!#HVðý‡ß¡‘lr赉 3ºÏ4Áɳ¨Q!Jm©ÜÛÄ3+(™¾Lõj~çéFK~3æ­,)›Ç»Ê8LœÓp¼ùá—[‡±ºšƒ0/°ðz†OÈÄRš·#?„(wraˆØxšWÒÒz2šª’÷0Sm­ª )YQà]æw‰[ÆŽ]Ü`‰²·OáS1±÷Ì3Qéq½ÍUw¸òï˜pKÿ”÷ÕIs—\ªŒ¼u;J¹äTXà™{ÑLƒ}z áó@òÆŸ±"Cïñ€ZPjo›Ç=Åø ¦9"´á¡±iLuÊð$â’—ãx$"X8cœp²Gk˜“9ªþEœi!7Ü×ûÓ€ ÝùáŠBÅ$ã{®åæËz¬õMèëé$Ãш¥ØÌè‰rd3r‡{ãû0{,›Î_•…‡:yKââ]:Rž•ýƒPø‰D3SÜá½ñ÷hº€Y@úÚêÓÊI~MHdê®xeM|q|Œç‡ó’óÛ펶â Á<°7’Èv'íqɬ÷çéR2sžNÊ\ŽpÞŸ×"ƒz4|•j‰½Ë^‚Y$Ù°ÿÑ£>%åQôWŸå¼Ù*’[¡Û›õ¬“dR}Î@@æiOŸvl°ÎÒe{4ü­­?£X ðãêZt·¯Þt+¦ƒ¹¬z†zåÙï_@G^`9‹v’ 'õsÔA6i]3®òÎÌý$A5vÜèåuø]¢J½«ðŸßaCêuž?{v´÷·–ÇÁ‰Rõm°ˆºÍrqŽ,ÿ²‹¦B6Q\ý²ÛO©SgP<ä×p]Lð(¥¬PöÌ$2I¦^7K„±…Bè¨j¥©3Ž´7#¦Ö”?UdÛZÞ'yËv€p’!HMúÐD +笘ܼB0ÙÿWK£P[Dö­t`jî•îC ·™8ûÚ?އzèÅi§2ô¢êŸ·sfJf+Þ`"=•¼”v韽°º¶ZÞ Å¨ÚÉ6(˜¡¢YÆKq£Vpãi]…¡o}gåûýŠûóñý7Rg¬"6ƒ (™5û¨Fµóú6ÞÎ~ùŒóðÝ å'¬ºÔ±6f†[C€šq¢>’l™Ü2|52Üh»ÿHÖ‡Bef¯ÿÓNí&ÍL"_fÂ=8¾ð-OJÌZÏ«$î çÚ¶Äû’Bý ;€ýÐÓÈkí‰?½Þäòxfu §?}3•+÷Ê>íWfŽiר°gYÀ4ù[BŸF&ï¢à1±÷4hÈxåLooI—ík·°’/(^|Q†$x`~^ ÁŸ x0v¡œ2ñ•W)1Nµˆ w+gKÙ£U :Ì9¤FEñmmÙ€ôƒõyrZ©,¯o·ØtþFxìa[d›#>ÈnDAi`‚%dÂðç7‘‹úíÊÔWiž‰ÚøR³÷ÎÖµŒBTd]ÜJ/¨6ƒóžý ÊØNýž³ïS‚WÉNî#î<¬˜ÑÕãtÞ+ò×¼Ó Ff¥Í™¯0J‹™ß“~jÐÕÓ,RŠbm]¼[`0Ϥ^¬Ù òšbsbê3£Pbß$xÍC è.%Л¢1qU~—¬«íNÐTÃ޵ײZ0vûÔÿ‡àF¿vk¦TªA[:]ÆO› ƒ~*t«…Á/zÑ %^;‹>ì-®<—!zùùÊò§£TÃëC"1½ÛkÙÿ|xÈôñ†zV/”E%§ðµÑ:§& ãAzÌvCp8wrÏ–yó•Ãü¾Ä™ /¾RêQ¿£ Ô#„y‚¦ÒÑ:56&pI \²Àe6?ì’¾ÉRÖÌxÐã\Yõ#ép-,ÀnÂö}é?Ô_©×j2nn³hŸyÁáM£$Œð¨ãU?v]€58º­ kB? Ìf€b®ô×Í•õ†gd†dRà°á¹œjêfùcâFÞ¨0ŽYÔDÐÉð7kVIC¼NJQpöÒ©ÑÌ-­ÆXù€74Z$¨±Õ™Ôäpÿ)ëÌ\»ãrÜõÄ›ŸŸÇkÊ™½»Üã·þ™µ'NŸ$ã€Eª¢]ì5ÄanSÑ/~EI¤[?ͪ_a¹’ïZ ƒÛb]*Ø Ëm»év)>o¸†²qwð D¨>xÃȦòŽM·–mh£áköøÅÓ¦œŸçMе脌±í±tÞ]ËÆÑ̽f÷Å4͘[ÝÌÅþh\Ú9Iëy_©^Ç {ÀÀÕÈzÁM*Öd%Ðë6à :U õ»¸„…¢ TŠôϾòoÒX‘?%ç(œdäå?Äɯâ—Íík/µÄ³^2Í Æû­IäɱùCYØ´h *•Büé4ñÛ ÓPÐoQø,æ,¯è“^§Jß$ÅèÝ»¨’ì õ)75À†éÙ„Bí.KFK‘‹µÈ~¥Êë ~(ŠÀ;™ ?Qàƒ—_¢+ˆi¹jG´yh¸®ÖÚV[›ós·p!ö²FP ÷þ”)Q× †$™>é‰Íµ’W^ŸYët‰.¹C6曹qÕVé ahÓ ¸0N£ßâ“õªs`¨ŽñôcD÷ìWd±} ("RÇØäÆvÿ@âÍàš]Kžªtä1dY]õ¯–qÏn º.Š0<Ü Á·oFbë* Á\¡Y »F£ZtZYE½AâávÁm—vΤ¥”È Ç‡õ[³ö Ô Îp`ºù(p.QîÂÍÃþ˜¨ŠÍ+->¼©Ï/ÃK”gî<°M³*o\<ÊŽ¹†ËXóVËÞu´xÄáßnÃ70T7´¶ÉÞ&ÑÈQ& ¹7Û r½ýuýmòx©^‹ýŠÃ€¤·Xtïô›0ŒË63*HPÊÝÑ¥ûymvŒ°ð{PGñ‚NƒSyÚ?ä&K»‡•Ð0´>!8xò-—¨*È2„Þ󵄼b¼b†]†;Šuè; (F»µÇ!Ü<¼(7áŒLi4ÑûH±…ʯ±!Âi Jó3ðÚ‰µëí5?œŒŽµe »A=űë:ŽûÒB2šx©õu^DtiÉYÞ‚çt2òü‡%a•F‘ùˆn>¯ÜŠÏ³¥¢’%DÎ|ÙehÜÏh)ºt©Ø)d%ÀÀÈ¿#¾Æ„¡”å˵r&ØqÙõ‚Ž$`kß.Çá#¥ûQDÈ ÜÄ;øˆA#%kmÝí~`׶б*§ªˆøaK‡¸¥5¬$ ê`ô—Lp·Ô¼_ˆNÎ^grB5rk¾%û‘öD—· †Q+¢âpâ¯ë‰&ËîÑ‚(Ðî:@(õ¦ _½>zʈ%§âèüÙ"Õí°ÈÖàÔ¨mBÿ¥7°}+ôø6ÌÀÛ«þ ÷WªË$aÐÀ  w+ gÄÝ)ºœE«±àY Päöm'Šk0w:û‹×P<ãÇ!F©z0Ý Ëû¶“FK~gh1ç¼pð×UNÌk××%ÏZcßöîúw`ÓߦÝ× "ÒÒ'õ/ä¨` & ã ;A `[ì ‡f½}ì`5ãBYÊ^ËÈ×wqhÏŸðd‘D_ì™ø«lºó`§Qgiç—œoó¯ Ü÷à¾rWUÑCÑ"‹œˆ‚ Æ@IÚTÃ|£²Ò&Ίdúõ¬ý@ÓçCe%ý»$ŠqNÅA¸ªóèÕƒPßt¯tÕèÆð—ƒyÓžnjê9K–ÙkßÏû@ö8Þ0=Ö1,Dzy™-Ê¡!q²±3Ö‰\ewuC$±ɃÍ(>°°Ò TF”"¨ÿOpÙ„¼pÂ]­§ V\?@ÌÌÔÔ\óì>Û?VH{XùO¡/ÍJü~¿uÎïyŽ sxΤv4Í¥¨½ë‚aói3ŸÜ芬…5D§Áòž7V–\ëpQ9 çÙÂ[[õ3÷ÀßÏq5Ê‚.Á<éù_¾«¼ì …rƒcÌ6Tlo5ÀXX 7Yû[àÖî_½§’Qg¸„hæÓÉi˜A(øl\ITÊHFQO\VœäùYÊ)¿.”áÈÊìÚËw;3€&¸owðØØê% þr¹{Àê‰õÂÛRµÇÕ½+€°HSÁŠ˜Nè‰×ʽå3õê» \N9ðå²&”ö—³ž¾•¹½¢µ I1ËïC5 '+½ÁŸŠà™¼Uò,п•cÇ YÿÞ :Sèyè¢@s9“‚Ê´ÜIÈ|©©µ\’I|–P«oŸã¹ÇC¡y!idãÅúO36E9À.RËjo;Ú^"/ò '7ÝÎyxmž=Äw€Ù†6- äîO ãon e™Þ ëè]¢ÄG›ßVl¤OO€ ‚g³÷ÎÁÅÚákŠŒ¡giæíÚ´úïИ7–ôyy m[,þ ̹àÐéÑý3åÙ7äV³ É‘_Ç,¹>Åð9u—NI¬4¨êÁþü“—¬‰°‘f¿«¼"!x)ªž;왘Ülü<ëi6ŸGÉC˜#6ƒFñÀê»Ó!  é©žü&Ç v¢feuuânðS }ïòÚåV8FŽ´ìëf;“U~»£™qí|Œˆ£ÖiòÈ9è?1(ìûs¤ÄÏM¼\`F-æ¾|9µ]P¨oaPùëõsËê±B =˜lî‹Ó±FGöŒäh+<¤ðé˜÷¨;_x6ƒA«>‹éÓ-§êvr#QÍ꣑]˜SF‹uîã<Ô7éËéQv›Ú®8–ŸÅ‚4 R̆„7”IÃý™%È{¦jàÆ­¸²•¶U[ý¥ÆþèǽæÀž»ôÓuY= uS™©ùž¶¥tO\kÍ­ƒ„ŸÂHÛćÀ­¸r´ú¤¯Í3hHþŸyÞ4õIÛýË$ÿi¨ËÔc7‚AÞ¦ÐË-™\)Ë*/ªœ¶þ¼‚a¢› cA <Ý=°£ÿ©©ï‰Á"±|gVB(ÆžŸÝE’Øä-Uâ ¹¤…]ÏÇ ݹqMU\¬Þæ‘Z¾o(Ý…â†Q>°ø°±¼$ªûÝD ÃG˜¼öНx×ÃQÈ6¼>y4ú‰y3Ÿ)o[z•,W¢^Â+Š÷-AñU¹~þ00Ö'ìùž¨g–2,_Âý܇–(ãy+¼[sžÅŽwͤ "‚Ùû^t{™³)s¼µÖ·NR‘Åeû5K]ú»7³—¹ TtÒPƒ›o;*^)¿ÓeÀ ¹` åàQ ™/8.>öÒ{HÂò»ÞKÆ#D\ñ‡MAø"Mu‹®U½”š‘cçFV©gOŸQTjHÎ3PàÍèó@ꎈ —Œã©Áòœmª;Üýü2Èf–ÕÕ‹LÊzOaY¿(š9wÜ„¨ÅÏàé{€Ðàç<¬íéxwZ6/‘c<¦ÇŽOZ¨ç½"]òh²cOt W5Õ™q;à‘‘þm9• TéùTaŸ RFZ²ÊPØ 87yp7„`q¨«¯’àlùøZ9+há#ºEéñ(» ‘¯¼h˜®èœu´Fâô¢Ò£Ê¢*Ì$“¹'w@(ÒÇ©ô<Á£·E^,¦„Ü‹£¿ÍÇåÂ+-Ÿ&#æHºEþÏîA]PZer%1Ìn¬%õ7冠bºp ““}µ¯ùAþ¦Çò¸5W;ƒåGAd;'.Øoö[øÞ,®Ñ°:yçÞÝV Õ\šm¿N)â'ŽYÇ}pÐ$<ØÜ…!ä?sÆ™Å_‰­¤xÍ9Jø¥]ÔÞ¼-øÐS:õÕ“w»ŠàŸ6PñŽýZRù(¹¤ÎÜÆY@ЧÀÅî Cz(øVfHïé]~¢+úñ粎3úOñfR2rv›6ºi¤[ov0\róyMpòø®6¸y¯¨…}³ÍÀÝRO•µÖõÈvL¼†&°€›ÊŸ*:’&¹Beg2fýótQærv£¿äêcY£†ð‰›bËiõxa¨—ï’¾¹•+=óÉ…‡•à3Sv —*°ˆßM%ð“¥Ô€›¸T¼ì•=¶p,-;_fåå¡cè‚låªK:7êÂ_ôÅB@”6š^Õ>—2·ær.ŸK|~pKÖîGàBòœ×KQHÞ¬líC/‚ì.wÜCSűG@RFf»}Q?Y ¦ ÀeÜešbg®®RÅ'U…w‡¾7Uœ…G4“âçq  pºá&:ô|ͬNÀ_IÈ nîF^3Ï^¾:C ô2Û&º(ù.á.!G8PiʹÒlUúßUL:Ո蓰81K7ˆ,­않?ۙʷ¦ñ‡o6í^ ¢Àºg«3ñ‘öFƒ6€¶EŸ ¤±·åô¸e¸8íÇJÖY^0‡) "HÀÞèuåëóÿ™Ì°Z¹²§¼ý£Úùýß…:Ÿá Åçfwž!JZëêoShëŸý‘mOïÄwdrnà–-züÀÛr¬Ø?ôFÉú rç‹{ñ§z7¬ ¯¤=ïgNZtÔ°_,þ"å#í5µÛÞ Ã|¥å‘ŽþŸÞ‹éütÐÎ ®¸22@˜"ðt<Ò…Ê6ü5pôEOîi± ö SŠÙ+[ô›:Õ’êvul/Ùgk½Xâ>ÞM¥šÅálçeˆ“0j”¸MÕgp“pð…Ñ¥ç]1Ìw#±ýhæ¥P¸·¸(ͯÃÏTèx«¦:¢4²gDíTñóª, åÑùtë Tÿš¶ÿL€uD„o°PÄÙå"©¨cÿ}B/›O·]‰^ÒŒ †WÖØƒD~Žßý‹Êd¤õr à'âF‘³ª÷ݹÀ :lÿÝÀî<â§nJ\±f¯òyŸü¬>kß ±½îìd'3ðTô¼wwV§!n³(ëØšgƉGæX] qf ›õ1ÿ½øt—Ýû4%'¨2Epœg¬~ߣx!1þ(oÁÅüL7Ù‚Dš74 î¨NpØ|—Ó ç5*ÃP«E„ K¨ƒÿãytÝ+JêyåNð>^½chІú÷®’=ÐÛˆÖ¼&©2þF§’SËÁ¶•Èn€TýÀñeâzsÉ BÞ9ƒò“œsctáÁæqM™ê0_›É;Šš½'ÄÌÝmßБ”õ5ë”\Rxüwm[3¬Œ?« ²QÉ ‚ç ܬ¹ú¤S-Õ_„É4È%°ù7逆 åÿÐV¥xA ü·æàÿ&o‘d^ÇÌT[O¢³‘Y+=~Ìå°†0ŒAv[¦ÚÛÂ%Þð bŽPá.õžÊ÷Bµ§YTÆJÄL2£=¿8@ík+ÎJ(ŸÒŒÀ,ˆºa µÀˆ>¥JùÉÙQ-v~E ö î-‘hºíl nÙÝËU“ˆM¶y,òÊàì ±\ð£Q6só[ˆQ‹V›a/½««„{þ<èZ„};g,4Z´Ö†÷8ŠÀçŠkÚ“ˆtBU“ã}Ûi%úØT•sår¶#é2HCÄ!{Ž|Ü´¥NxµAÐDs8j-§5Ñâ6zÚ÷ÛøEõ«[bõÏæƒ’xgÌ$mf±j=T>µ"!^Ãt˜k»déôÜ£Ëa¿ôú&f~ØÃo)*À¬þr°0‰›•Io _ç<¹ @õßagKã;TG×dGµÊ&DÈ›ÒQ€ÂŒFr;{ÂõÅš]¡xLÂÔÕ/_RQü« ØÀÑÎ]Æ›„–PÊêcª;”Ú’«ôª±ªq²Ú5?¼„– êw«,ªGŸ£¼ùŸ¦NMhŽû/VG?kœ‡Y½Ðõ,ðˆÔtRWåÓU>§°MrÓ[äàK”݉`Ž•Z°½Ü]3žÛŸ$4j Ž\Køµ‘rg!Ä®\êM¼«˜P‹âNâÔ[@àa/åêTÙ>¦{y›ñØghip³£“4+ºÊ´á†CPmR÷ ‚õ‡¶•²_3„Qgl”ûÆÎÌFAU]Ê%Á ÄÐuK"X·MtÉ¥i˲ØÜ’Sc£G„#Ï<5* á÷KÉD‡Q`&&ÌC©ÅÁG9:ß86ö“¤@.‘IØOÁæ\jë›DãwšX®Ò Ž]Þ0ê¶1Ñ÷˜‰t&ϸujþ÷˜ã@§àöÝ`È´ìiôšÃÍ .+QØ“@Ñ™#ü‘Pj'ÇãFnܽlËÏ—ýª>zdÔâ3EÔ[#Íp4@%yèΨԥ“Ì6nXÀh,Ólڈƨ`£Fã}f¢bŒ”âZÂ[ÔÙ /,„f …Gô ?$tøí¬Û ëç¦Ðfíṫ‘¯ÿ¨wÛ‡KÀ’Õs€?Z’©aÈ{4°)ßBUˆþþpÓË2déaÖ ùqò¢ »@ þåö4\;œÅ^I-{Ø b€C–¿yoUñƒÀb±¡HFbkS$#"2Ùi¡•RuJX=y _H€0ÎN4 –tE¤ƒÝ£€Ž$ãÕƒ†J¸ó¦†^9`ªÔþ­À$I ]lý/$ÜÈ¢C àð!ÕϬlIÖ`‹:Á+ Mÿº;• tþûŽ_X¬ Ý ©bË ¶ó«é7/OWÓYWw’²Ä€¡ƒ¡‡dën¶Îw}nShö~åiWGöÒ±|•ÏÉ®Kq¢ˆØ}¯»}â€j Åï™$&^AsË»6s‹¹ CCu’yÎ9Ú,²àÄ 0åTœõ5û)iƒÜízó©œØ7[X2önû³¸=Ö¢&Þï’1KÊ4®­ Áñ†³k.B_âP;¡:§¤¸.”ú_°J¿Ãç"Û4Ÿü-ƒzå|…vØG*Ô:Ì©Ïx4¦Zc§L¼žV~¿ÒnþÄAÝS{é-¥ÚÝDA´Â(®UYùVÊõ{eŸ9¡ ® Gù2ÏYÑî2[v¸Û1ˆ|æ¨X8á¥Å0Obdç4H¯žÝÊÅ>›”Sse:úQìÞ?+ŽZSDèŒÇâ. lûVYlÎ3åuÕ@ÃüäÉx¿Lqô¯Ì}ã˜$9ýK𯾎®-ÓÓ‚Dx&C§óž†É?® Ýý"Ôà€WEo {ŠÇv*Qöym£…€ÚÉNßÃÆQïù‘=Î= ÒŒòP D¥“韼.ŸËDT–XÐxÅs^¬SRëE>ÍÒ£36ø2%„EÅDòÒ:g  %h‚ÏøÙæ—é?M(À¥â]e+‰|ÙÞÿi™l©#nËL¥õl§ºå´¿òã0ÜåŸ;tÃ^¶­z—Vq@ ù‘ºÒ &®vÂÞt2ÃkŒ‰íó[<ÇåîÈ×½d<k׆¥ó–†ºZíŸ Î$âZ¬ÿžRõTЄf¯C5l+ŒÑÑ}_ýg‚H llB×ݺ/â-öÙ1ª Â¢ÉϯC:h ŠœÊØG ƒâœšŒ-öË]‰5øÞ€ëw;¾ƒ•¤‡„ޝE£ØˆN޳6ïÅS침{\p©íz:ï’×Õ’¯í¶• yîIåU&cñž2ù+¾1_Ë rÜaó¥™&S{89µ¯/:j¢g˜€$Sº\5eå\h' ÓC2±þ’ý´6–h«O¥Oo˜ ‰u Èz²i³ô•Í—alÔÀï 4ñ÷ä—/ð¹;‹I;@À±õÇ[ŒFªê DtŽq¼á fOÿkÊ ª1´?Æõß,TõÖ‹BwÞŽ÷‘Ð[gÿ¨Ý ²ãÈÀQ<8b!¹¸- hsc¼IÚ{xÎú4ž¼eÈ‹%OÊŽJDÚÞàs¼é6¯voø”?³£RÓ€Š[µ˜Â§&Ù½¼mì„4^^¶[úéä¨00‚ ¾Ñ¬»j•=šÔDrÖîŽ Ò E+vT¼ÄÖ]¨5Ýxv<ÆÀ-_1?_³Ú{}£æ]ÑÎþH^‡ÊY1¿EU×Jy ÓEÀ'#P]ÀŸ‚û$°"g”ß²9ì*¼ädÒÄUŸ¹tãÐÌ݆RÃòMû·ìúœØ± –fÌÅiJjëØŠË=§·…¨.‰ÿcä o’vómããîö|®-â43ÌŒ$£¹ä!ŒÐmÜ^R"h‹äMBþb|w–$¶byçîE EÅs89Ù¼eKñV(t}¤{··$‰ðÕÔ=ša_Î>hÍŸçw uVw—¬í½ 2Q¦<+ÓsaÑ-è`•Îvs=Rýp.¡>®ê ÙÎŽZ”¾—¸¼$Izm¿%4³÷õôP%ÚÈžÃ%3ÕÛЗFP䨖•œA¶€4%ÎìTg6š­Î‘ãõ(W{Їi$åÜ“Zªšæ¿ v¥gšSv$ g346+ÐêbAwàrÿµªRÅ?ÃXÇrÝâi V™q4ÕÔZ|í~­Æ@éE7½VCŸįÜ÷0?u ~ªhÿâFÚcíÁTo»ìøÜ\:¤&„¤H“Î÷TÌwG œ‚QþKßÐÃà£| Ù$¡Ø;{Ťޗ¹è3p¥4?¨òVà çw'å›éŠü­¨…¿ÒÏ®p "EÓ »q„—4{9æ¼-vmú[:n'˜*A=ÂŽä;Ü<Ð{#Q[¥^wI›4š¶”ñ¸õÅ!Çló¬ƒÐþUŠ>à´Vó){µ]Ü ÍŠÜ’€!h£”7)x×б«3ÂXî¼c2ñ4+·Á#Äà ;¾>Â{bšNˆ‹Põ´­hG;ÊMMÒÓ};3íº'xô W¹«Æ.Ì„Ac”´ð§ié4B†µzGÂÙ\ Ó9äÙyð˜1’'º1;Åû¡âÄÕȈقdgÈ¥àP51ØOM$¹ÌóNI,ö®5hMsÙÂ6¯ÚB‡•`‘Â{¸¾Ê¶ãWQ€ï•½ÃÿèÛêKáÐa;9úøÙ@lÚFabï BÙ=2î>þ ê–•ÀÚíÊ­ŽÚªÛv|ôÂßÌ®ñ‹Ê-bû…‹. Q#sç'¼Àc?SÍüå<³€HÙÕ•·HXŰüQ;)6¬þi޹cé’aPW•¶£@émˆèDm‡¹"ð®r äVçñŸ]v)”4{£Ø8ÞÌJ¢Ië“¢ø‡=v3orjôÖ¨ñKØ0«Œy7'ŒØÝEhŸíä5¨iU~]άdTí—@ÑŽG[¾nùj†4îW*r«Yá#:ÈÏ×~ Q¼#$öÛÊH”“ 17‘å×ÒÍ&iôž‰ìüõ:ÜgÆÛàO*(­ ¬‡üN뜅Nõ®½X¸*u=5_uOÈØ¼ì|»#H‘Œm_q»ÀõØOMåëx[sZÐÑö Ù  #ޤ?Æ3©©ïJ4hE°xßU¨Èö¶SDˆŠ?ÏõûO!›jyõ¯ ä£ëxBô«ÀU\ZÙ÷iv¾q…¦5Ã’t}‘TG8'„;ÿ¡‹™TÎ;®ÕƒRe§¦qY«k½Àަiøj‹”p”Yè¯x!&‹ÞúŽ©YÒ8•Zç˜f…`Íà ­cŒ±W—@j²žŽ4¼©¡;.Šü„ Ò:Y¡L'ÛöÖŽá\^ÈD èóc}q9âË·y®Õ»®»‚´ _1±gç%A„/mytZA®I¶BŸvVÝ3WtúD©BlHD•®ÄwjÑreNX¸Ô®mÝ_ ý£õ°â§Ñ/ŒFC¤“˜V ´Ÿ x ÕÔ¤k~j€ÞR¸It*©þêôà€…E¼±¿°ùðË´ý/£çA&©åõZmIf³Ì´áøGd”/ ë&içâ{\âO%k?Ì:È*ŽÄø½Íøºàãð<‹„¤ˆ²N–~'ÉA"߬aÕ­¦n‹T²jZ— HnçÂ…7ò‹Øg²3½Øt¶ÓŽÚ3wPÜ ”œ[¿éžPW1›®ÿHáøy »Ië%c§Qk˺–Úµw¶“ÎŹÑû6\Þs´rÊ€öpï‚Ò‡ò.ô„ª9z{¼Ë×óu~êÐÌA kD¦v©Öc”¦{iST³“ ’pß듇v¬=;2½ydFyN/Á/‹½îŠÝwF†î%Ú´E ¿]ë?ª*"õŠéEŸÜÁÙQH‘¬à*©ÅXȲaÉ‹6T®–øyœÍŽ?y€Þ‚VA‰¨kE¥8ïöü]Ù²e?‰érÛ$îl'¼“H+¶Ò¬ …À:Y\,#¢]“×÷O´ f%T"ˆ’¥:ÿ´ cܹܔ9»ÔË6ï°xˆ+én»3SÓo”håÏjÍ o˜U·Õaõ¥ß”b¦Úc•‡·²¨ Ÿ2Ckö²Z™ÔÜqõª–*Ò„” ÊZôñÑrQ)kñÝ‚WëY, è<ˇKïHÛŽÄJ•Ñ´x2gìP¼ xØ&DœÖÒÎoû7ïÓ9Îu¾˜-'åX²(Õ9 -Jð$P`%â‹!Týa¨‰ a î¸7qäöÞ6©è¶•ûƒƒ·Ðº"«Ú¤»sd™àðÁZu+úq°ÌqÛ4¢›%M…é¡ò›Q[dð€w -¢|£4pÈ$Ù;,htpXº9`µ«¤mû:“=ì³ÖK‘3BîNöp•¡õú6ÉœÃÛ2%TÃ*7Ò|œµÁþæ!¾ïÃ"L‚ÚzþÄCAÖÇ­[4„²f®1'4 dŸþ+ý"EöÝʱ•]ˆ&ûK€e`¯Z['õ%¥–»¼"` ÍO &oâäÔzóM?´‡dJ&Ñ·žó;ž?ŽÀƒí/n[TȸP,Eèõb¨õƒU”P¾Îmj±îz{ò£l5?nÄ)Õ_:.äßP`}„pÀ’æÏÀs>Ö$-ÚÁÏkµ„ÄîV˵ûý GE+=r^JÕll‘Ýx1}côŒóÂâ æ[Eÿªß€|øÛÅúWIç&—2­†¯Èïµr86¤˜™v òR`xþ²l©¼uØ”×Ø|ÎüX yF›ÖLüua²É̘Ê*OÔ@_Åc(sæ½:ÍÂñÔ¥þ¬‡ú™~T†Ñ7é×<^ UÄt4=ÀÏYIQ4D1T‚Î¥¿}PwÒWåVT•2Ж"΀œD@­ý0p¢Åå )‡ù, ØP~µ5œ%lfj®ß†›œ ´¸+/ñÌ•IÒA¡Ã¢òÿEäâ²SÕG£2bâ†vûMî†!ù=û­ÀS; 5Ö‹eaÞË—Èe-ïŸ@ê¿Ët‘øç3 ù<-Æ4ñü3š² Šù˜IJ˜ Û¡£4tþR}—´úá'†í±³y‰OMêÒÀ\¹sƒ­,ÐÊñUƒ(DÜ‹ÿ;ûèfãhLúÞ½õÝ‹¥O²ÞpîÛ»÷ÆïY±Yœ…ZaS×”s0mâúC–YM¥ëã¢7üëE7ßjŽéÌ$¹Kù!#O›Ókˆñ*<…îŒBà X ËìšËÕIr”CMú¶Ï‰,Eÿ–wY„Ï?t"AWXlÝoµ=¾¼#÷Ìi` 7ù‰ \ÄÛPϜܭ·X*ˆn*–m÷Äì™a#Ò!‘ö^e‚Åjs#í«ù'ß0‘®FÜóÖ@ eî%D#ÉMŸ Äa«êª²[Y¡àE±¼$€vQ»:Dxe« ¤¸v¶ ~׎ÐâÏSG¯ùvÎTÞõ(¢Œ %·=%ãm°ÎV$×#¼ˆ‚|÷™}V;ež«ÃÍzl2ÑæA&GšéhE=î ¼>ý­ñæ"»°iVï=Ÿ;e—Á'[„¥÷32Ë÷×›ÃÂl+‰ìæC‚kðhËà¢ÅuþEᎅeRg#ê>M`.á±zmص¤¹Jö"§Ìb}?_§¦Äü0©XžØØ{(œ´î.&Û¿;6íGZ&$>Ý·_í…Qt÷ÛÔ°wùBU¿Òõ}¿g¼ mÃvêÿä‡ì(† ɶlzå"”ü¦9&Îxhý»‡còp?ùùnp$ÄÍ7Øó*,±)]?™ß"4JÈ}»tžÝdÂߦ»Ì¼7ÅÑI† ^ÉG?;ÖÆQñÐ ~+‰Ó qºÖôEvÑb–§ë5bœ¢¸$"3uK~ï8xÿJ¾](_ÐÊ\˜(|OL4JŸ$ÌFX¡ÒÈ¢~Þãu)˜8ëkîjÞ°`#·Â ”'v—D¯ÿ2دí^)(ò°~Y81$eeà€v«ëc¹œÚ2ïÅ<‹ì¼nC‡{Õ{·¨a,F[œ)ŸÑ÷dúQöõ¨‘o÷ÝQ4¾éÊO÷{®ŠþÙ°X§<ß«l-þ!ÄYíI:Öô®íé¡Wíà; %ö„Þ¼#‡Žº ´¿€N-רL«äkí£7j‹®ÇlΪpWþ&U>éy>Ïç4%Š­J§­Ñ “öœªÄ™íi“²yNj‹Cò0ج6zXã¡»km(Šä{D5ŽO(¶QŒœ×ŽÔ(u ~BHD«V»Zš û@úµ6•,b8¤¨õš%ù&ý”RþH^KŠä?7¾ôâ“„ Œü|er{êá·¸ž7€Ú^…Em)?ÿ‚ Ésüî›°'·ÐŸ¾,‘‡a²*ò} Â@ È]§›H ß>Ò¤<9—2"mqÑilsàÅ=6u¥ŸÃ~_ž 4ñ¨Ûßyh*Yíé’€ˆ äTÊû¾¡Ô"XO&à9:ê\×áÜïÓ³3DxܼéÊ<¸SôùkKÎzéeçXc!õŽ- WÏ·ìß™iƒÇruq²VâoÈ¥ly×çÒ‘¡Äöâ­[šI¨7BˆÇ[9—Å·4˜öᙈFØ9Ná6D Bt”[›_רÞL8kQÑp´FÑ2’înò_Ê…ð¾3:iSR>Ri”&;{¥”Òÿ‚q5K{Ž&–|j2ÆhqöÑŸh‹ìwŽyªÔÞ!ƒSa5=C†G?Fë(ö­ë=ä·½¿–É’ƒpò±ÊâÍ•q³ODà˜dœ‰.Æ5˜’¾Ÿ@G(zÄ-õëC¯‹3?Œ”Igš¶{\ÜûcpsR¯«Ä–ðh‚cæ{Âh<„ÎÍ0}˜W s¤¸!}®¾M¬´Èp—\™§”Ýøßã?,ê ¨5­¨«¡’L`{Ø‹?FÞ&ƒPL $hÁ—o’·"ÜÒr”“K°l©ËËÞî°}iΊÎî+å (—ßE¡0~=ÜÏi©÷©‚Wó;7²ðþ6/*èml \#?ïq¶¡%|¢ÌbA$¦0­õ=èØãÚÛOS8Ø/á}¢Ž9N.õæÓ‘s®AR»Ñ¨º¾Çs5·%H]áV©Ko±f{n¼Þ¹^æëš”?m^§†T:üÞn­ZqèÎt*¶`…Ï žiq¢.¯Jšh7¶Ì¼vušø/r‰vH„“uùyëeìqÇ/+Soå“X\ò^w‹â“·b$¦»Z7ßÁ]}*ÒˆÍZ}µ²yóÌ/ÄÈLs””ÁÖk)Þ7a’GÅ`Š´Çbc‡hþ(Ç”T_å‘“o.í¦zdƼø¹x¯Êª‚48u_;Bõ6X]ñ±¬¯ÖD\°ËÖ/ÝÞY¬%ÑütiéÀP8t]Àެi(qÉ6;¼ÿûéù‚¨æj…‡ZŸQ:æ»jý¼ü%[4WöÉ•„X&sì4kÒ²êè‰ä åš·p¥\Ô¡¨¯;»Šqáó.zWŠ«i"†2··íì‘¢÷JÇÔ0.ö/KË(Çùô­=a:‡§l¥ŸÔ«jxÐ:2¿êÇrÖBˆ Qk#HCW=ÌÕ`òü»h¿³Aleëx{õ®¦Æèõelßfr ¼¾…±6Ö.ç1]ÁôÝíÁ%ìfü qg7xÙ°¯vTºLö&–UŸÝ‰\ŒÒk.ÀÙu\hXZã¢Ût\öPö®—Ì“}E¹YçŽK°­ãûx¬ˆã6'kH”Úûwì[§›’)?÷–ÆBZjm”èîY¶û·Èïl|¥®ê½ÿ•nùá›ÏÝC[ÓF0ORAÖJ i‹ ÅP#„ÀÆuçSlb®Ì¾‡rˆ¾Æ4…”u«C{>äþwÀ[ª]ž,fêrrå„í.‚³ûpŸx?Hê™AˆõWÍzcŸ¹·™ O+—‹–¸» ®<ûu ^ñŽbåvHA·Tý/8› ¨b3›P-Î2Ô~¥‰EH>ÅÍ1Ì,½2GBkàËME’v1¦1¹~Â5Ü„õcr–°­c¥IªY5GyÔúšéhè’×v,†2íë“×±œ¶–Aÿlõ¦=²! Uñ‚ý6Õ|¬‰‹ë”¿1U–ü"s£ (À PSsÛ£åäÏÝ{: P=`ŒéRt ¦]=À2rÙ§wâN1 ¨"íW‚OdïîËþ{´p„ƒTã¦y¥/ñ-ˇhJ¼™M “TBPÒþmtÈQ‡¾«¥é O™WE®G¡ìý¶fƒµ»GRiÜO.«`¸œä¹Ë‰ `÷ ô¦-¥³œ}=SäÕÌ„Køõ¨âJµF‰ÄA«L}wÿ¬^Õ‰ƒð-ÊÁÇŠ¡Ëñ‘£†Ð—‡‚zÓË©š5V²zéÀ²ê`…±êûî.ò ¦%eÈvÚ«£­†‰œ1°¹óå @aüzã±ÁFš¥@XGÀC‰¶2®”Åàaž“9ˆñ'EÃ=׿ôaç—M'ˆ]šD¾3üKºŽÇSGéªÌ•àà"q•RXý–ÚÀh—¿ýº å5çcpzÜspC”ÈaRÞ.4ý} CÖåŠß~î¶½m¡rU¥S¢ £LÚ;Ž½ÎƒHT¦–ò9˜Ï'Ζ“•3ü«–bUÙèú½4ˆÅs‡ˆåG?)êó?hÁÝ]~ñÕÍfy‘ÃðŠß&ÅP¿T¯Ëp¹>:iÅu¼¤ÍóxVskŽó5Á} ×J ¢u 2öd4þtÖ­ÊRÒ°Cµû3¢ê,t½’õ*Vå¢ëú`SýîçÜHï'E,âK.eTwZÖNûT ÄðζETEvóFVVD\'ak†åfÀ#ÉêL#Q7Õ‡~tk°ÖåZ[}ƒóõ°,¬¡Ä?0ì$èW´Ø->SÜéh—]rEäõcb[q¨^Œ„ÏÃùšŠþä< wcÝçyYûㆠc€,é€\ë‚ô üh­7yu¬‘]¥Õö^A^¶4éùÖ€½!¾ÕÌÑöÍ@*u? d¥íªÕ†%ÀA…+гvÅžÃÁåÆ=xôÇÕŽ§ù&Q%˜[á¯0ÚhFª3UFÓ‡+Wá”›ÕÁCKöƒÒÁÑJñr^.Mƒ£…âê^ƒd•Õ}¬Ñ‹N´—•6&Ðʇãî,Då#rM]]æV/ž,Á¬âRåÁÆ‘©{âØ?Î *GéñÛ/Rê?:û…ž'ÃþÌý"“`ÿª–QŠ“Û'”߉ ¨ªyòÏg­ö¦.ÿhs ®¡.ÍøàÞ²âècR8 ú}¬†àŠ­ûĺ}IÊqnJè!H·ÒÆÐ”ƒ€x6JE%˜ºØe8«¸„k޽¼—'4º×ZH/7hrÒïøáñµÊÛgážýFAña1ªµ¬‚Õ.ˆýå­¹#¤­2ùPüsçÁãdE ®¢¥5Ó‡`Ý=õ¥B«¡3‰!gâûšTÙ´\\iZÞSm\O\H¨uw]kû4¤ÕÀÌw ¼â¶^ ‚cB«P<¶ &L¾Ú¥ã½›)õD)ØP¥ÔQ¨ÒÍמ•-ò2J§sVmHbL@ ÂD‚$¦Q_˜CàÊŽK(# œ7,ô‹MU[ð5¦åþw¨KÁ¯‹øEÛ¹U¶$-&™xíŽ{›4kÔã¯+ ˆªÊ\œ¥eqˆ-PÜ*NÂÃ:2Æ;T‹œb½4ŒµÍDíK:žóÍf[Κzùòâ æÞžõþi®¤t‰;x¾©KnÃ%;úªñ»¸Ì ênMMƒq£Ýü©®¨¶»iÉ´L¹DG)y¤:žbôþ}-…‘#ߌ³ÙÝ‹IMøä¸¶8T (¾ßiÍéÕúd aq€1ƒJ <ª¦îI†= Íö!q·n}ÍÄó÷ €Ê|›®Vʬ{§­Rà-Ìv'QÈ6“BG#« 1rùeh[—e•àL­¿:Š‹”5YdTR- úeHû" ¼Z曦Ý1ùÓ<õºB]¸[âí¯nÙ¿7¸V÷ë‘wèN&ì'ÑŸÖ™WÆk¯ÁYáúÎþæ`ÃÑ!þº«qM夻ÆÁ[PšÊ¤ÞìYžj@‘O'q~T̨v¤¸ŠÙ¦†àºJ{/Óî?WÛÔÌÄV"ç/Þ ¹hiv&ƒàjæmœ}Õþ7Pž {g¥ƒFªëüàWZç±è¦*èð5­þºáµ¯K:´nÔð¦òä0› ÔÿlÕƒ@ˆ†öøSãØLd„@7kµÆ¾pÞZ‡”Rt(´<é³ZœJ°ÖÑp+úêr{HP0:ì)hÚ¾§÷“e,8®ìyK¡Oig™»ðFÝ®ý·,kÕ‚6gŽçÇàƒ!ü{•“NÖÂVª´ ;!âϨ²†ª.gj¢Ñ|—ð Þ!Ú~'€a ”2¹P&ÇÕª².Ú*s´tp©=L{B‚J8×»ø3ùÿ Å’AÒVgðâ7x£{i®¬Íµ‹ø¿•TãS$­ñf0 äLi’!4ç†ÄŒ¨q$µŽÍwE=©±ÑÂ[ oNtšßÛg²UGïoÍVöEË>‚áçÖa­ä¹Xïo|C—áÖ÷I'Y “>yað™®ÕžÙ‘dúªWõ¸1…°bEA+”aÔQÑ0nH¨o=‚æîzTô4(_À%°×¡Òìoueydo#Ç5U:”ô+£{±/•»ô”t« ªqG'Ö«µÀEOìeìÝΘ³àI7[À°Ô×P@P⯦õÇÀ欯<ÓæÛfÉêåæD¶ÆkâÚcq}Í„¸ê2ºswwqÝb1@/ª¹†al‚¿ä’N¬ i7ØG"6’; ÆOHâõ±O%tÅÒÃŽ˜?-ÐĖ٠ѽŠf3 ™åÒH¢B)5Ù+ÜÉܵÁ†JêcÊÆýP» ʼn=ÛÝ5y‰w’˜kÈîR«KÇõoFÉ¢§Q¡(Ÿg»ÂÌ`W¡–i'KBÛvÿ¶ø£U.6Zɹ-Kå„EØÁtKí· 2´êé@£»³=¶‘™ú¶‚ÈQ&¾Ú>§Ù¬ÝGA–O³Ì^ŠäýìNٲܢHgn­ \¯‹^*c…ãIc—äNb¡Md\±­ZŸÇ³ªÉHˆÛí4l®’”‰à=>{XtYK4Gń̵21šŽsí¿pÛ¹š(Ôs¦vå»|FÚ!D‹'\Ú¢jã'îø:NrôÚe,³æ6f÷°³·Þæ‡\úRœª†M6ë^K­íÌË0:…ä%<ƒæTðÚòãÕ Rò£@•q¸aœz^~Ep‹G|uäɈ*m“L´ïÞA išã†ÚˆŠ<£:2‡Ün‡®BÜœ˜§µÊºº»›M§ðÛØÙ‹jK Ûméò`BRJ”Úî/ImåùB<û¦B÷Ì¢T øÜ’è§–?–ùxþecŸãU4õ†ô­€>¡UòDX{^Ö 6«N¬ÍSØ3˜{¾0Xùbg²³;0I{Ÿ¤›?å‡Ç^£²À*Ò¿ê §ÿÊv+µ¼–ʨ[ßT—ó}KÞ²øwM2–Ôp¬*dœ~CŸÑ_Zìd#š¿#erûÿ8‚ V é Uì g¶”SïRõÁ! ×0| @ô“œÕlr±•'Œ%ž‡‡,ãPµ1wó/œ â?!ÚÆxxö¤kxþï2³KV¾ã0TálC½ñ¶'š]ÎñK&E\ä´Em<ßFŸÉ uÞÈ!9—Y¢ìé²ÁòÌí’oS$‹­þ¬Ïw4dX_Ïo× [L]¹&UøÊ m{"â¡»ÜÂÈQb, 21kEš|ioÿ¹¯°Fž°ä‰È㳺³“¯ͳͮåÚòwjsÁ˜þ™)þGÆÛwoì#³´b·Qh'è9Mχò¦á¨mã¥KRùpÉ5—¾Ȥ 7²ÎÃd¯‡Â6FØEq€k\F7Õd|¿™¬` {¸¹.ªïBä¦úGº"…ò=¼øº´SEVâ®âL(\¹|OÍÑÉ7/C€ëšŸuG ÒWƵê5‡ÿäÞ+ãX³ 3íÄô¤ù8ïÔ?Ìi…mÝ|Û1Õµ*p‘Üzñ½ÜÎ ¸GðXú©eµ‚Ýf¶’–,p„ OÂÀ CÝÆíÊ<Ì”?Ûœñ”þä ~^æT«€ñ¸¸Å=²ÈÙO×G¨<Nßÿ_Üf 2›Î£ÎK}_·ïFÒÙ@BòrµE÷pÙ¥¢ïÆ,€ÐÙýtŸÈý¨8ò—gîŠbÌà3ÅèËD ^_âˆSÔ%›Îš/ÏòášN9“{ÃJ6æóx À^úü &`ôƒvØ\š oç± Wxš>j½˜tD‘ù7Æ~ æ‰~eO*ÐÃyCd$À¹Ù ‚ÍIg­Fm+zµO¯cóDJÆ>a(F1#ðºˆfÍñ«mÚ’2~5%ÈøÊ­6öŽJ†?ÊP¿˜;qŽD({è°uZñÖüø“ÑÙÆ%Æ Ü¿Z9xQ¿œ²™<e邏4‰ªp4 úâ2‡ÂOøA® ²»Ó›Þé®-—ߪ͟¦H=\ŠîÕvÊÝUE$4ËE9ðúAXÇàx– ¡ ”5q±‰³£;.\Sʼn^gFýxmÕÆxI\Ɇ§3ú¬Ž~IÔgÉ_ñ ­r¸ª§>‚Ù±~|t辶Ð$Oê'ÒWlè)>e¶}Ìb+ÇöuãÈ<ï¾k7(úαäÖ}Çß—Ÿ²0TŠmÒ,æg½ âÌŒp+ó’nˆ—%O²ÌxŒDó£ì=å´cTÞIáê-‡ÂøÕfc 8µúàe€ˆÄµä£gzKš5¬"SÐ_(®VA¡%¢y~òàའ7õîk„2.è=3¸`ñÎfªg­»q²G"NÔZŒæ@Ò~qŠp”yåõ¾T†Ðñ°ssôOa4£­-1häIçŒ^YVÕX3b…«Á‰ô;äU Z}¥Jý?‚ÕÀ£UÓ¼–Þ¿@eï­Ê›`1mž¶ù…°S²Ð$!yY„®œõd@L˜Âè'"o'ò±h9YiɉðzP­]0´ªÇjóÒóœ”)œ„ØjªÆ„•mLl’ ja5’l§óV,ŸÑb;;¾ÖT±ßÐ(n'JâKƒ_òóôþ’ иQ:ûÂÐÌ4zаjæQ¨_ðoµ5Ú%êk­¹À9$½Æ˜ Â8Ú8WÕÜÁñOOȱ£ùã˜ù‚ÅD@¼A¢¿ ¿Ìóì‹2™rÍLßúÝI`¹„?ÂúxÕÀù÷‚³&»Ëé°‹Ts0}-hÕÁà4¼‡ÅÑÑØ©áïÞ,Ëýß ÙLŽ4š™4jÆÄúœIȵ¯vÍÒòŸÑâ úA"hD2rñµ˜ŸjGh%ådçM°¹¾JäñW]ÑÊ'ûO!R>¬hocFuáYªx@S-)ñÌî3„Ì&ÈÅKb†Ë‘ýûÅn °9~EîÒ ½Üÿu5 ÷“q·‰mµyq ,á¤óe‹•"OÞ,yÁjäËvx.áñ[-¾6W\w„Jê!A,Gms`XÃÉ+¾„ÿ\Y³sK UOún/DEî7‘/A¿FDíZ³ðÊo×8G¸4ëkÚWZ—å©Gâ¦ÓØ µtJLnìœ[Û_Çzî/s­dTÓ…ì†[ó`øÃÞ¯ÿÌ6”'ÚG|€oy~‰ÁÆ <VÃQ©_Â1=‹œ²ñûðUÿ³¦d²´^c«Užà7ÇV7rÄiŒÿv\8Ü0ˆx53 .¸D;úš—öñC‚ßI¼)ºxT—ÊlyêõGï(¸"Ö@—¢õJOÖ÷ú31ê° ¹Ìi©¢€_…&_üÍ#ó~"–P;b8ñ¡&ЛśˆÔÐ_Ë5lü±ØÌ9¡B”÷TâòžÍõB™ø ÌUó‡½àÇê4 Nÿ]}ðE° ùßHÞˆ×6#sgù¡îýgˆÓ.…]ï C»±|hRÔ/’ªŸ3™BÿÊg´Yáå5.“þµ[}m?GìÑ/`¡̨?ºJ€ù·1¬…/H&~§>èÁ»c8ßRœ»i£|Žâ÷L¶•âóJX”ïDzi›%O6ÎP0o¯0­#«º®!½06{4¤¯ù4מ¼…È£˜¤3Ee½yß%)Ë_¾È˜‡€.€ÌÌŠhʵ"u÷(„<¾ê{ñ!ƒ¦Õå\+ÿ0CiR–ÎØ·0¸Jst¥ŸS0âŒY­Ÿ@ˆõÉŸ>z‹­U$´¶¶~ÏuWÞ–{ö‚©@r/ÐÊ9ç ã®vS|cZAÈ%tAzPmCé=)­—7Ãgÿ¡Ž×§ïÃ8@,…;š©s±€€¦c5ByÖ)Ýr¢¦P.Ë/é©™…o¶Z[A×-Ê—:2eúUÛM]k&çñ’Ü¿‘ß¡tëûkœ8%®#£æ²(¤µZ,%ô $ z0Ðjð³ìl.-DÓ§÷!a?mï%˜(®]×|ae¶Æ0&¶Õº² £Q×Ñ/šôå+û¬áEâ¨aºY[.™\Š/?>&ç XÜ¥]m£Ë¤ãMq‡T&tr‡`Ž!“)EÈ pçѼü ·¸JIã3y‡5à'å t]È7D‡J òœ˜eƒÊh$€¿„ÁU\0O8À±(2"©{J3":òt]ÆÂµ¡Œ´ oǽs9¡.ªeŒ®çcrŸ6¯ò}YØ „Ñ@éè}ö˜ÀÜò‘‰2y+¦M‰âÅ«W…q/8§pÿîMZŽÍPkh{aÙ1y&tüžÙòÕMoó¬²<ñ/ÇÖa?ˆüʯu݇Ójû–,¨Üå@/GwŸMa-èGkD}¤ð©ƒƒŸfZbYÑ‹l‰t/ ±Øj¦èôRŸ”hCå1âÆñ±S@ÖòÁ~e} kÎ º]Ýd^T‹’´WÀç®<ƒ²±›ÐK¥ÑÀiT̘‡ˆw!u@Âp2„÷AÒf޵ò„ÜtFIZ^iÿ—à£ùÖ5ÐsDiërÿ$›Ø0b6Ëü~xŽÏ·._Ï–Òõ…Ür²`wYù;›ç¤²å»äˆ‡E3óùž²ëšvÇ»Ó'Ÿãµ~?— •Fh{‰tëß– Úö >NÀ^²‹Jà-Û[æb3ÂàÉ'é[fÚcBl¹†H(y’;=9ÿ—¥¸Iód¯ökˆ‰'R6"œdÞqît¿œý,‘Žß¢]MöV>»Ñ@Þw†M0®èçã^F`çFÕ²æL((¬±’S¢ÅïÂy§púÓ­Ë’5›íy1‘pÆ{”uxëÈOþ…Ž'¾7+Öº!íƒ c´Žè ~E€×þO¢‹aöb]Á3LQ`ÉB徿Ýh ¸xdce 7¼#ª,C!A¢¿F&Uì ÍÎ à=¡¤Òôõ"+Øèµ7¼¹zÕ½¤ ¹}D²6 ù?×bÍáCfúþVžä¬oJË™ÿ€ø›-ŸEÚÃ4Æulò¿ËûYO˜R•´²vTNè~õúÁÎóg/âïžÇ¿¢-;g”Õ,W¤MܶÞ|JÍ€çØ¼ÔKýF¾)—$N\&§^» ¥C1sà ÓTÆÄåò¿2,õºU'ë\Ï鬘ÒíÄ;?áó^²ÒÙ-|¼ˆÉ$˜L\|¡Ý¿õzŒ”%aí=xÏ9Ú®‚Z†7¼ã(Ìå±"ªÅ/t^ aå³KÁ;ï"7Åßn.E%gì¢i@ß@¹Ÿ†˜¿´:¿)[ÒÐ…¥ Ê.Ç3âu?C¸¹‚ä)tOsÒóŒÊJºþy>±Vq/Ǔۅ9‚[Š$q·QI‚f¯<£>@²2Ô>[ì ïe©,ÝŠßiÝÅh'Ü|Iª$’¡Ù+šûcIäE”tÒiÒt6›ä¸ßE3;Ý´6Õ¯qIk›®Í#®Z<ª:ÄÞé× Jâ`d¬*»ö¬(a+‘Zê mºf'hß®gú[ŠœÓÖ—kÑÅÞxñ`1ã×–7÷`´å£ò<Ë ôcƒ´$(Œ­‹c.æ”=…AfÐX£ª—.~qîôÛ³‡A8zi5ëµkµ‰RvŽÜ%Þ¯ ¼×s—4_ ˆ;<µ$â!wÉužÇÆ&ʼfDÚõŒü²”ªÚfK>¶°ÐPVoN’"Öõá‘§•6{ ,"›W&ð°Æ§´û&RTaÈc\} Åta°Àj)›HèÔyÓW,ªZ{E¯žOµpk.]3?5Ík]¬‚‡Aål³¤!Bd+Š‚y–׬NÃD4¶2мyÒå㙘ÓóXŸLI9Åã0ƈˆÂŒCè–¤;ÇÖvœù½?vîûÆ[_àçºÞ"¬<¸ù‚Ç86<ä\µfòjq;íâé ‚ÂPåC}BùâêUÀÒµN£5«Èm]¯ëô«–’´òÚPËuÁ|Ý‚Õh® ¬Pt„xq_ÈEìNºUK‹¡ïä FåTùk“.¾± ¾KiÙ T‹OÝî-ØEÄâzÂ@§$€¹c€ïÊxЫ/î§6‰Ìp@ÿÆVbc¡ô‚RMgµeaFb½Ç1­V&CÍ¡ˆ_©Š>¼/Âå†y1ó•›ßcºØ„=Kûÿªß2Å=±R"oŒ‡!3'öƒCxHœÈe ¬ñfÞ÷ÕÍÀ(î¥u<¯ZóƒZ\ë…Sb Mêi «úå•è(7g-üs%å³lßÐ1:O,'ˆ¡cT™Z®²Gö™&>ã0ãC4”ayösS°x–ÍýUâ )š š$Ö<Ò:¤¿ ·FDQ+ÓB$sh×äî úÈãó,ºG5Ô Ê¿†`Íþ}”út³ÃWc^NÜÅáá0 î*ßk)}“#­¸ämnKJ´ÝÄNEƒ¨ó vS5ú äÇ/²±^b7i’›tº(>ŸHM‡ ßìæüä‘Åû$ƒW[¦s#8#!Àç8zË2“Õ©úâLÖkÚ¸@ÒK,E Mƒò’\’ýŸn.ÀÀµµ€žÇ/’eîI­ aá³âNÃÛ|¼ç…ö]%ʧ/Y2™·÷›Œ¤(j°ß¨º>*ÊÀ=â;uÌçÒ~y»mAu¯zØÂ[£–#™ÇŸ¹úlŽ@ÛÞÃõìéxâcÝ–<¼t"©âO¶ö¦IJ&%d]*h%U†U¾â¯Üª&îB SÔgÈC\S·âFÿƒ‚T£kZ[8<,”8þÓª ƒ`ž¾¶‰¦R;Ÿö˜b½d>•Ð-l†›¯ô.âá,Ä[k¡–C žnk¾pî5RÝ=\>åÞå^ƒbHê4ýÍ秉3'®¼K2AÀä:6Q?Ý}SÏ„ú1r>kf«d'}Ä#˜]žÇÅ>âàÆŠ~·üòÏe¥nxªfZÑÂoX§OÌsmrT¾SVš=ï{A·£7*ÖsÂpqA•íiÜÒÑŒG¶4n$uÿÇRNåv šºÿ®Ä*ªh]^ü¢¦t*OT²R6¶žÓ@9L‚¿ñ’—>aÒëù6j–f£ƒ·ª;˜ƒ%ù«¡‡¸ á)‚ÇÌ McÓÝø¦nÞPþCÚÃÃWzÔïQ“i$¯Ü¼A¡ סÉÅ<5æi²$ë0>Ô; ]/G#ò+V²RPk•©IY¸Hªp³U¶qîþv»9¿ª×š¸³n¹OV«Q­ã‘%ËM¨…µsßUUKm–ŠLäÅü‘q£—Ò¬+ U_zÅ,ælöõkI’aM¢>ÃÓ9DH’+_qMˆý :åÃ+;þ £iB‰ÛƒŠ¬¯ý¯¢b_eʲä—ÔGT™uþÃ:þiNVÓp´¦[¯±MëëÏÉúÕnÃ(óBm8¼³aIê±EHÑÒ òÖ‘º^}ÈIlGÄ›rõDϼZÄtŒýR×G)•¸±‰9¦hÝýF2uËçîê½: êxÁ'2jU“ÕXíÄÑLÏ}øÏmMŒ°rþÑdÖ.‚Ù°Ï[dÜ€†q$û…­.M,þü0Ê(ÃС=ÏM¸}(C÷œÈµ¡S‚Ùþ |bD¡K¿6AåDŒ{u—&pøñXg¾ð¡Ñi}Û!q[œ…IÝFåb¦èOÊþ9͸Àpæ÷Z¶º¦Î¬„Ãþ~Þ¦?a•¢'žœ![aö¡³jÜPfqíö­±pê%Âúwôô¶œÅ rUÍÆì,5¢S{ׯÌ/Tª’Õ |BCÕÉŒÕ^(úM;ÿÀCÜÎk¿êseD  drâ^Ú(FsêVí3ŸÖ(N‚¤pôlELáªPE/*!pÅëÍ"F<¤€Éˆ“üY#ˆÙß§:w—¼ªÖn’DQ-¶¡Uvæëö w§s ®ˆc!º‰_³üð)Ï"[ìZw:ápWV_À® ;tOTqº5¾îWÐ_%ï+;n6»Y虼:D‹±'Ú FPÂÛ>ÀBù_?<®J:Õ•Id;0‚¬!–ì¤ãàÒr-cÞ{d ò<òÊ Aò{ ›0c\%§¥p9鯪ŸÅ8 û;®(`ádAN†yæ¯ð*‡0!»ƒZàâãíue¼è~xÑr„ô(؉Œ*õ¦äËy“€8MˆÑ$ætÇÓ¢ô#šÂ¬ðe »øÎâ%Õ {‚§ÝïFùXœ€ãÙ¸ð›Óò¯QF‹r‘V¾{yËó‰ZMúg &ôóî.ÕÞÎMM¨×¾ Ëz+¹=×;–L]-Ùó¤Òyìî²<gFľ7t+½iiÙ€gnÿTäWòb•ü<ÆÏ¶»F«£j SYžÅƒÀ 8±c©Hî™ 90ª×ä4°œ²R°˜é]_­‡äqEp¨œU&ÉØò<¡/=~øXâtšÙVû¦×Óó_dŠ6Ô÷nHD6t"ßkX(Ö¡ß{žÓ¸Œ2™©UªÇd_ø¡ï@u) xW0AŸR~Kô×HS5RêùãIõ&!²ã‡µò8½ì'VJÖ$Ô7Qʃ™‹3™¢•ÐòOÃj³Üô:M5¢{- æú°Q¤ äÃ{4¬ Þý0ÙxE™ZB°ŠT²±sÜÂr~¹ß, ëÃBìÒÿOdîíÕšZX(p)в(*"™ùùp­,B•²ÃÏ#+º¨°,» [Ò#¥*„»?ÇqתÞ÷Øå…7ó¶P¥w°£&„›ÂB ¨—ÙNU.$ïT¨¶«#¬0~V;Íâîc²QíGx“²' NAÜãÍÉdÄ\ v_ŒÆCÂ*ô®pþà4Î ª ß™`Çͤñ紪ݤ؜óó†ËÀu#¶N€€Ü:D¬c£ÆÊLääF3 …“|a¡H|S,³[w€Žo&ŸSL#ì%üVþw•]ú5…p*3[Ò„ùÕ˜#qŸ*ߊºîéQ7zp w-J¯§óS±–üÉ«_¢¸Äš’8+›"] e¶˜G‚噘1/Nã`#ì= ÊGö)D¥ Å h·ÒÂ,ÑÅÛÁLÎ0­ŒÕy­t†#¯ÚZ…|团ôÛ~«Æ fM²JŸKŸÁNÿ6 ì©ìÞ¾bT KÈŸ]¹ÞÜ„Y)ÚwÒ?[4ò©Ió¦>G)žJ&d}ýíÜŒÅÓò~Ø0 $´N냿´Èc®pVqí+ëCppG¾ùˆóßeõœõœ6GÌ,öfú8z”Ô7»S[¢S50c­›Ôq/”_9¹jó¿·Ü%×­tQS…“ßîLðbkÂÒxâe¤í3SðXG¸T¤J@ð«H´+†ÆW™íç´upèó`•I]± >W*ìÕ´$FZlEfg sôë¥*|zº7>ù!žI©Åÿ«; ¸ao Á¥e5MB+ Mø¡FËB6ð|fíbî š}ÍÌ­š^§A¾’•Ëâ¦}VnŽØ†ô.¹¼j*À¥-;Ù&ú)Ñó‰A¡Z7*8é±51Ÿ{‡Ïo:g7Ï.Lå7û.éñ²¯ƒE‘c‰Ð‹}tIÙØ*I ø¤¾ ñOWËíÅ'as\Ølð\ÍL¡6þÒF)pm­Ø,€•º·¢ÀPæá¸EW0d¤q]&ÿdV6ß.cùÂ~L´óðCß(¨îMëb#òEnÑ»PÅV½!Àȑѵ Ç jFÇé¨J$ǵÀcu?„4·[ö&å‡:1“&OÓö(øyD~EÜžù·ÐSF¢–ç=RËÉd£YÐûfG¸¤Í§³‹À;\ŸÝuJï,J„?‡NÞ"¥‹ñ±{ÀôÎ%µ øvN1ëÈôDü•÷Lݶ§ÖwŸ£º7ý:Íî•+†•ô$)Dx U¯"q ï×û4úS+a:ÇÞK ÿ÷QöŒ*y ç–5!ýÃ< ïþ¨è|ƒý‹6\ U+ᬮ[®eVéüvíÜ{ÈL+]¬)–ùxþecŸä溰ÿoö“?,‡Ä›X‘:¯Oò9T:1G4qÞ.ÌtÉÑ‚‚ëEæ‡áHԟ׋¬¡ª nÍPÑU7/˜ÄñcªXâ§nc]¾¨XŒPœ‹ayÚGºxª.wÈç¤}¬ÓÏÇž\r—f`¤„ñ@zJnî´a'¾¨s‡Š­NŸÔAëG½PLˆ6ºIQkí úº+äÿ¥ ÒKëÈíTžDø.yžÕ¿}‡ÀÄœiÃõ„äóä1íJ$ŽðdÍ=² óv–¡t5!(«:Ö+Ovl<¦ih^ý þj,QüYº‘îîÞâÄ?a塺Á7ÝëÜÇbÖ¼GÈ P˜MåoÑéïToãw¿dyçëÀã·œó6ês\Ô…‹R;ÕXÚ»ûÿõåöÁ¡\Ðs·~=ðÈTDŽÝCCijÚ`¹ÎŸÔ¬\·‹ðñ™_“ÿü§™¯$Âõ9j®Û¢_]L“ù’¦8áÌæh²»BJÖÛn¼ûXÏjY—”8Ò6騋í©YóZtÛt´Ìn„íUè¨PGØÊzAý+ÚT¦M1¥e¬åx£4AŠ\ˆÚ‡2;¡W³Rø}×!ÔÉ0àehyXÍbKÏÔlwæ l_%L;8ê8jßQüg-í× X¬ŒA•JòdÔ×Ã~Pl¥+4øð7ç©0òhذáÐQ@s<ëÍÚ¶}Z‹P€åñ µ˜‚Èc×?ׇÎXªN{Ò¾oçÀù;ËÙÍ@ê[våÊ)÷3šuEzØì>BÔ?t_Ñ ¼9™G´H|®Ö²ñjóèOHgäì,Û[$¤BCæ °õJ³öëOP_GçUV'žuƒÇÙ/{#KÑé¹™˜qÈ~|Hë8àäpz2Þ8«H8*M‰œû’wÇÞºå Eª”pÇ !}¡1{¹Œ_ZšlÈë¡ÁŠ;u§·+ú,fo ä-AÏ[HM¥×ÌÝåìtò*9¼Â^’щ§a–‹Û`B>/Cö0Þ÷ðišNË­þÊ âÄCHŽ´–/9fV.ŠÎÉó”6!œvóÑ@ƒ ðÉ!w±y;¯m$i¾äµH+·]YA|åÀD!j{‘øEÙ×ZQ5»¶'vgêæ¿ux”y–#Ú^Ž´¹Q« 1ªAä˜ØÿPâ'4R‰ÅU]¥‡xý'¬¡Â>¹æ’îtê€3Yêy.·¬4ÖçæÍÕO“߀®†×ñh’¶˜ap(AXž|§©Î±¿[‚ÎP§k vá}¬WŒ(átù?þB¾æ ÓÜõ'åqMä±ýE½ŽQéæ.Eö“g¤«¾V _‹ ”hÅ:DB¼ªO^ÛðÍÌkUü°õÒ| ¬u ýÅxTõtWw!BQE–NZ˜ª9Pvíîs³¹AÅ$vÉ®?·-~¡ò:ŠL34ú±ì0=§§ PøCV9´IØ{ã=Ž·ÓB´K yѲTp»~Ëp çévÛD5í¬ð2Ia‹¡EÛfåÀŽ„îŽ9’-v‹òIÇëmÄ»R vDo’ÌÎÏ÷ëí8t7}²³U@èpܸEHÕŽý[ï´’´ÈÎx·¬®#7 >æ &2Þ÷VõŸœ6ÊnæÀ­NÖÚþÿñú°‚Û…6[þŒõTo¾¤tœ®ã¥VøŽ![ ²]w¼­ ?r$T]µÖn°ïìÄ9?Æ´OõQÚOçU­§Y34WóíoxÊ2î½JÂ@Þ ·–݇_ýÚÎOeüõKŠÂåýÒÕ¶~~Y‡ö’*Ó}+«r†l¥‚z«° :¬Î­>2yá®GmÀúÀ„ ¿”À)Ûäý±,ƒ¬RŽ~––• ¿9e(Œ tÍà3ÎWZŸ«IDÊ$hDpãëYGÃÑÂÆ*ëq¾þîæÔn7T¾ÅQAT—FZ³+žÔu\7`äpß$ûòðSdSÅKôB™Ke$<Ìßšfœ¼”“p‚騸ag#au.ÁÄè6Ý ˆ?áÌcQùí!;äùãÀdõôèiÔõà !S½øIAúiù7ÞÃ]×K¸¾1|bi”e¦9»:…2)\)1§ã¨š†46?g¨Zgš›r¨'â 6'BT̰?©Õ_ÉD[2-8?± %_í/ê¾1%Þ2÷ÃÉ;ÌÆä`¢Q ÇI ý´‰#Ç€µFB P ˆÒõUwŽYdù>-µeˆ‘ÌÄ@Îå³uãšß€ý^T®®ÿÅN ôÅ&Å\lð6Ý\PPÔâfÎåzg˜Ú>B¯Áà!‹/P>8Ýí#PëV¡׫»‚K˜éù×DÜÛ›ñ#¶Š_ÊBQÂîZlJh ª„—mOþ'Ò5ↇ{°1”W(ø® —= æ¤&ïZ³NtÉÁ÷œ±á#Š»2©Da=B(œõxing‘:öÄžö5¡Ãջͯª—=¦èa:ô+j9…Q=\]<·ÂÑÞX, ÌÊU àbïIE8Ò¾ž*}»Rr–º.uR“H#ì&ƒR= —Cð¡z¡µ[“u°êßÄùŽßë"¹Ü,—YN~_U'o[g¦´ÏKÕWSÎ’5³ðL51œ¥ýÂ7Ùðy¶wúCÛúKŽ:XãC —$z…¾ýØàÒ²Rªí{Ì=.Õ줪Kš"²ñÞ^Ð <å½G í¯è”;0yøq Æ—¶ ¸Ðb9ð}ªÌc…ë rŸGµÔfôCçU棖0e²ø1MÛŸƒáï ³¿igÂêFõ/™¤‹yˆËåÝ~¶‰]\š<š^”‚ëÁ¬‚úC¯ŠI¿(T¼U<´ÆÐy¡•ãjÖ>V»HYeÛ+3¯‚áLã^Š_‹]c–vR –‰ãÒ‘ ÔòlÞÿ{!‘}²æ¯5âeœ8rÿNç&°³:|®Ûr·”½¹>U»Ýáaªp/÷SÔ$ µ´o>rP$Çî²UoicÕÃÏßëYéŒò“e»ê‡}ޱÈi1ñ24¦O­.Å>“ú¦µ9é%I9ÄùZX<‚QË  €on- šE3–?­-ƒbmïO!͘ØP;o3:]©u’¶eõ:#ß\ßh±_`ÊDLYF»"úQýHÍWÙ¯° H3'–¬í@·Ø£ƒ9©W²\hAºª{FñÁQ¹›57ò)°k½« ú^Ÿõ#°§Ç‰Õ:èM¥|åH0)ÜÍd8& 7tɘÕFÛ@ä¸QÆÜuX¦q>ÏÏ…ì«Yš}W ZÇ ™(9ö£¨ü|Z*íØÃôzK£âißh°oÛ²¾åH¨ÉH6í-/>N©Ç=û¸`0-hxõ“²–-#¹ßBWN¾ÁðÚ‘Þ±ŠŠ/úĉz¨~IÓ{‰nÅ]ê4õuµSظ~xª´£ÿÑ¡‰Ú5–:‡I âšÑRSÎ CKÐÙÖXâ ¨¤çi!c‹z2v#É+×XÌá°§×þlÿˆÁ+’b*¡ç#½@8(E$IÍÀ8 8ï=­ _|( 6,vzTïÊé›2yabÎ3Þ¯<å»XˉÅh¥â­ž¸gÔØÝœD'Cí Ž2å¿Üv3 ¿Úé÷71á¶9*Ìã<Ú£Òÿ|Ì`9¢A„;’£4ô­™irÄ|œa¹[^1–pÔ¥ž :¸[쇋q€šu ÉšâÄÆQ—4“aUžðáß¡O5WlInò]ãj|XÏ]ƒ/77Š%‘¶‘gç׊pJ¿”€î‘º§:AÜ«6!4ÿ¥ t#9ªÍÃßlç/mÛ ‚m§¥'Ìú­ÅŠU«(9Ý̯‰;­ ›AI¦€V†m¡Rµ[æÃVG Š#Ëè¾ÂŠÛWoa±ÜW)šõ¿uÎûñó`á…}íÕç_Àq4;•Àrc˜ë£b‘‰âÈ4­#S1ÃÃÐpb¹w(88Ëò²®8 6]H§]‘_êPèµ¼=Úñæa7Â$[±bøå‘Vÿ¶¼½D¾³• f©Ø&æÇœ+Ëx¾««±b ”:h„«”¡ ¦/†Xžæ…¸Êó%p W—ÔñÄi¶ ¯ç6Ð|œ¬4J•æ<Øk: a-Ä*TBÖ‘Óœ‡Èà›K½ûuÍ(¢vÓ} ‡(Åñw'Ö2¡ ßËuy“²"vý\rIi°•sà6Z>ˆÿäY©•»ÌÞÆ¶Â†ôYÃ*œ1¾@¥m¬Êüݧ(m©¼§N£#·(?Ö‚9Åö¦CmÍ‘¨ÔFÈŸBÆ~ÿ£]ÞNšmÊ_é‹Rå¸CÁO\Íúü¸?óFIMYY>Klð¾rø3NiéÙ ;¾Å™œúÕ@7™T•ÂN ‹qØL 0?ðè)L ¦1†¦µ½n0V¯Ò¬®ykKH“fö›ŽŸ‹{“UËŒÌNf`Þw –ÄÝ \>ÀvºƒF3@J«ÌíÝ}Ǩ?ŸG¬§Ïä$¬g#Àû„èþ_À}}Qm\«ÞävK©37 ‚Û Š\ñΰ™ˆ«< _GˆÓy,gËÖùá§îª/šÏtBÛu6T¶¦kq¯“;•ÇÑ5Õž?gEpÙ­Z^vf—Ü( ý'’åáÐ3×Jª½k‡É–óbïXšú›#Gºî’— 8?‹l8K?Çêë½Ç¦ó¹…=wƒ4rTÜùÌèͦBØæÖ¬’$ë†,É®÷X†±°íy|)3¿%žª¬g[׳h NÖ ûkGd«Á¯6:íO€—¦ì@Ƈ§y//–ç+*뤕×Eë)†_ö™OT?WKY/õ”@öö¸áÖ@e––wÎûså"Öm׉Ǹʲ:$·¥Vðr¥ ;{»ÿöTS($O w¾å¿“û¾ÞnwF¡‚¥Yíªƒ±›œ¹Ï[âïS‡rŒÔäKuò·½nˆð]gÂ'Lû\ûäíˆÊâNØDì65÷›SÎiž¥ÂJ¶+¼—˜[¸f4À:, 'í»ï{õ‚hóÉ|NíÕg Y„gŽVB+’°ÏÅFRTxàlòçHâ–q²¶ G»Ðé÷r)?UAÍ.FºR‹iSmÓ˜ó'‡%¦`]Ÿ4k§@DWtßõ7…ªHÉ+©åÊÖö¬F “Ÿ…÷òqüÊŠñ{~•¯,M$|F>õÇ™´©ÝÉw»Âœ ŽDÅÇZ©nÍ#¼¹0—o£0 ”³º¿ Ä3¼ß~Ð 8íÚó,¬†~IŽg×ÛˆBû²Ï:Ì“E$gåbý/r ”)Ûþ½%ý7ÑÚJ-ðê£Ìm… c/¾Fž½[CÑÒ‚ýtjµúÔdü!mqóö,”_Ñ¢c2œ¡?Œöjj¶Eû§¿€¾½­j×2¦ãHúpo9·£|}gÌÚñW1ªçà jQá>Õ}Yýƒd:ñ_öà¸@Œ‰ F)Ä ¸øbPJX0ð_ãûê endstream endobj 24 0 obj 100460 endobj 25 0 obj <
> endobj 26 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡GÎt‘øˆ’®>R4éuw¿¿Ï·õ?ÓåøoÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·ÊãésM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§mܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒßè·RŸ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßátF8#ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;ÑÈDt8. Pi|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-AÍÄNèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8eÁM‹³<—“#artË„F{ÇN‡® tÛáÞ®Lˆvqè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿdØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 27 0 obj <> endobj 28 0 obj <> stream xœœ¸steo—5ÛvNlÛ¶mçĶÍJŬضíŠm£’ŠmT’[¿·ûí¾ýõwÿ¹ãŒqö~æ\ÏÜkÍ=÷c e5sGS ¤£ƒ #3/@ÑÚÞÔÝUÍÄAžAhéø rÂQP¨[»Ùÿ G¡ tqµvtàýw˜ ÐÄí/ nâö·\ÝÊ ân °XØyÙ8x9¸¬ÌÌ\ÿ.ttáX¸8šÂQˆ9:y»X[Z¹ñþë@­¡ªECGGÿß ÀÔûß @èjmé üQ £“=ÐÁ ö¶³³6XÚy;Y¹LÌÍæÿhhšØm’ÖvÖNNŽj1šÿ©ò·Q†¿_p) ÐåïHÿÚøY’Ž.–ÀÍÂÌÅÊ ¶rssâeb²øKYüC1ºZ0:ݘþjRH8˜‹9ÚÿÓ+Ü?›Å­]€f‡÷fú?ݶupôtðý_°…µƒù?Òsw'& kgw Œøÿ…àþ³º8˜Y™y˜Y@gÐËÌŠéŸKª{;ÿE²ü›8˜ûû:9:,Lì\þÖÀ¿8_W ÀÍÅèïûÿ&þç Ž…`nmæ0ZZ;Àý·ú_hñk7k/€3ã_Ìÿ|þëÌàï7wt°óþïrE{ à ý_´¨¨£À—…‹ÀÀÊÍ`afeðp°üÿ§Ô™ðoþ…*›XÿgƒÌÿ-)ã`áàù9þøŸ³˜<þ#ÎêâLøú;tt³6þMÊåQŸ™ƒùoÿXþ¯9ýü¥õÿ_@ÿÑûGé¿“ù¿:”t·³û—›Ôÿá&௮yÀ?†Ú™¸üïz{k;ïÿËŽÿU©üGòÿKIÆÍäï "–vÿ6Àdí*ií4W¶v3³ú¨ý'¡á`t±³v*;ºZÿós``á`ù?Iu+k3[ «ëßú/è`þ?/Ë$á`æhní` Psû›ióÿþ¡ÍÜ]\þZü¯»üwï¿×Ö{½€fpnBaè÷fvåºyŸïÊÍ]TÌ´:[d{÷<® cJpÛ%Ð7µbß•©ÅØËfË‚M\lŠ‹C$ta&¬ûi°Á vÓ'QiÎÓ«—課rfýiþ¨LãááÀ±÷¹í¹­¶?çäírñì‚„Øy’=|?°M4téæ`ü±ñb¡!VÓúA ²áDø(Ó[Bñ`Ð`Ø^ÎÑ4+G·þÌ­Õû/zûøEáQ 9 ø÷_Ù3¹7õUn Ë”ÊyÓO‘\$=§ )„q'!WÃ÷S‰Ö–Ãfz'þÝ©ƒGÔ „HØìpdî"2’ª’¨ŒtW£ÌƒÂ_CžŽuöxHßþÌ)>€6Á üž¬±!¡'d@üÜšûY6GŸ(TëhùX}gcÄä÷qÒ¢Ï}1X[ŽcÌ÷5c=í{rÖ_dMȈŸK‹«{7t5ï¡(L(Õœ ïW3Öìo7³X¦l蜵<àc¸Kª‘?€ÔÏŒù‰DOÎŒú#n)gg+P7±Çd¨ÒšÛÅ/•gÎQwô4ÊI›çZŠZ~]ƒÁ¸Øzu º´é×ÈÎÒ/Ç×`h³VÔõY÷"-®y¤ ^ˆn² ¯º°{ã?\}PúJßH „mg ȹhZТFH³!qMÐ=‡)ÅèÌ]Òo\rŒ_tòäË÷*"P—êÓ Ï’Á¿±±˜3A:Ði01{!‹FuÒIta}þŠ5¥‘DÏ]wyžËÿfº8r¥ˆíŒrH´e”U;ÔO¦K7TÖZØí;X–œT5)3ÿ¦¡Ç\&Hìv…ˆ´ý†eüÁÁQ¨8²€ %nÏÈ ãG¹°cgU¦ů)5ïcïÜôÈÉÂ~+_™‰+§I{O긦’ÃÌ*Ÿ:¹Ï¿oJæOúö Ÿ z¾㈶û沸Dê;º '1†´/Œ-j*ÑêãXÁJëF9Mžça>ÑlS1ÂÜ„.êfƒúÉZÙtÈÊ­Ì ôþè}®Æ.ðKŠg­ib4—^fj9f÷êTY“gŒ!|v;îˆï"úDT’ÖÏo<á&J/T¦?&iÉ5èD)U «tM¨NÃ~uÌš¡—AÝ.ÕÈMY0m{™”Lqþ‘ÙQîû³w@ÑhQ*MÃC\€:×ÏÅ?Øìã$“¯ÆUÀñ™6‹ V«zêSM³Æ KÉjå÷ ¹ÍʰB2EDn‚zãØË ×гšy*ž—Stnc°ùZÐÀ%‡ÿ5¶ÏŽL÷GM gÞfÁ™˜ùåò Èbó1>c$W©ÎÙ³  éù©¥8ëÄϧë´l·6c;h2kƒ![-ÏôcÒ”™òžß´zç=}Tëù‹‹yí—k©aËk}»'õí”^êïJN÷ #†N‰vò&œ||·ó¡9]«ß„MõA1LЉç¤ØÑùsϤºD„ÎB!3’EoÃ8×ôh¥€†X| ?R$ºµ¦qi?¾ò¡æ>Q¤.(2|}5uÌÛ*Рád_†z¶û}rw%ãÏÅ}¨2ø4‰2‹RhxìÒ‚Jü×o„Ë"ƒîcºCò­ž»n[óXu¨C{„¡«íKÜv;ÏzÁ~™¤ºÝڸõšº³ w\”7;ÙûÚ†Kmwð¬M‘¼Wpžg¤š0·'_­ùK+sm~ŠAI[Ì™Jû캡žØ¥´^UO=ýc>µ5g·Îp‰nA™™Ž2¢9Fà%`Šîr* –™é6®ò±½à=¼:ÆÌÔc Ó¤.šè6¿Ö{{+MtñÍ`wâù@=~`¯ÿP~· ‹ÈÃã2Ÿ«Q?™ ~ˆxZÕà’JŽög-èt?È5û[ËrRââô.ö½ŠÅïÔ.CíFqx×еg—¯VÒ« >ºzƒu}£ÀõÎo3{ «0vùiÐ…—Æ2&1·u^OFˆ,)²‹þÊàEIbÞ~ÓW³ U9PO+ÙžëR&’;®ð«£$ð`²dX)~ÛA)E”{ÃÚkÞwpö$¢UÒ½ó¤ï7Ñ…m$½[^Sʤq£Á‡nu¯9E’`edRô1Ô?YÖŒNÞßœUØ\mi‹±ŽÌ\‹S,iø³hçÓÑíî—Õ8H¢Ì %¼¡2ø ©ãµ}½ZB ¶«´edí{¢·I;ÐHæ_Å;^ê ScǶiú4)&Þ%4¥·QWDë4/¨…[Ý|9§é¥-š‹U’Â'‡Š”nò?•¬÷‰ýüï"T4ÍåqÚf–iûíÙš,9-cáœaÜð0A»ã3t¾G4`bÎsûmŽn¦w×yÚ'Ì‚C0¼Aò•ϳÕö1w”-+êÈT8ìasÑ ê QjŒÚ°Vôžð„9ëviÕ:ç?QÅId¼JÅÇ/y½šÖñƒs0Unkg3뙈²d§Gèù\mVÛ£˜àÉä ÷pGQ YX?dz— Èo¥qÝnkŒÏÃT°&l:+‹ÍÊÒD¨{)¼ÒùʵØÀê….úºr-F'É CrÅà/£û•Îg9È>më¡Ù”<²f,JHk9…ŽK$ïɱ†v•jÊd\0ø‚qjÊÃöº¿%Uº(æhWwžG¢ƒ…wiä蛀ÜífÆ‘%lB';S)©ò÷§&Å«+‰à¢¥gž’C˜!îö„Û‰â-·FI<“̼×ÈLüÄRQ“;Ö€,Óœ‹*>/Ås{» æVmCÂ`±çÆCjÎÚ¡É-®ýd^hÙUSÕø05T•fNƒ÷ÚS”þ6<Ï•Õ%ÌÅYgˆ5 «oÞp[]m–¡ë,”(Íl $­¾¼É>¯ ®¯ã×àŠÂlZÿÕ±ü{¿omýÑ=ƒ™­Ù¨¼•e”(¬Ml/û{„C 3-0µŒó±ácé3ó&oçY}•·XáÚ1†)ÔŠï'åŽÂë5VÏÔ|ªþaEœÒIÜ·û?§ØMϠϣ)O½¦SH¿GM°Ö>…v`j×+ÈD–Ê7Æ`iWÑ’FÞ¸UW\{í°˜Ý.“¢åŽ4.¡}|¢‰¦Nèa¾B'µ!¿+£_'“ xТ ÆÒ®áÃ#é>#;ˆdÆÎ " åDù[…u 0o¿&•®Â=CÓHOeüü' Ñy« OL›¸{eÊcXJZ-{÷hH&]ô®qˆRcÙöJ¾½¸ŠcÅÞÑô>ºZÙr¢ËYIÑûÁz ’˜üÚ]¢b^þ4ÏbÚ&¡€ü qgÚ6ð«¼)í3'­ÆÏh ®ªq¿kôu-$r 휩ÎÜRI{S¹_W­©<$ÌŠ«&õ¢ 51²vÅÔ} y‹K$:6ëGCÙ>ж×kã܇‘p Î{¹ÊHÿýè>Ê&Ç™1Ç!ŠnÖÉçtžð*á¶.¬U¦ïÌÇ¿@ÉŸ<á¤J£¸­úV>ûž|DÉZeúl y,Fþz“0ÎÅ4,«Çti*©×È2×\Ý¡ 7Gÿº“¡7­ÑˆÆäËBMèk_iüÒOL3–yÒ8“ M}lT±:p kDT§ÿ 8¨}S¼÷§¯«íïÔ9IÎ8gg±Ä†gÞω ™•NI?jÆñ›Â•a£Õj$’MhÃ:òÍèƒxT'*å',cQ퀘¤7åz­¿p¬S^ï0_Ú¼­&û„zÑcvjúÍuÊiãIb½G,ñ¨õ+žÂ‘.7íÕÞךøwƒ«ëŽâó~<ÛAÙÏ<;µ<•Ò¦ñê’Kñ'‡ú<â8d¢ nƃ ߳ǷØí§Š>‹;9ܳ; ™_£¸åæ7É0¥aL±–¹¥ølwSºM¹û.™ƒë Ù±§QT¢Ê§¼ÌæåY!ßNå4©ć ˜&‰. /E?ËgnbÙSÂÙïrmu}Œƒ,°Jš}Š .á!J¤I•Ôjb°7K$°Ü&÷’÷žÀ²ƒË³ÆFìóHÐïÑM¼©ˆÕ¸ÌjŒ ¥Z"ÉAÕ<ñ»³i|qÐúÔ0;™ºì†¸Ì—ã"ÐÙùЖ,ÖŒ¶Ú>³dFl«VV@hŠwüØ_A¾êß&„ÏÙã¯ëoÓÖÊ ^¥$žiPt[î%Å”úéH«Eáb 2ÃÔÎ4eôEï’ÃѺi$Oã^ç*O;':°Æß»ã}œWLò›¨d9[MÙ-Î$)n-DD5ge¤ÐÚœè6´º`3ÖröÓ¹È_H‹[ã^QFÚ’­b©Í2D*ÖÉëy|Ýu¼²ìe¶èW6™.›’CaÎWýªe,‘ ¡ž{›2øËA5‡‰¤B‹%.Él¨‡ 3ÚIŽì…}$•RÍú ÔÖªƒ4!1Ì5¸£Ñèâš?óµ´ébBýÕ>v¥Ì6‹C_Ê_ŸNûÌcÀkh%æR1Ä´"âM*s‰·Ú‡ùò;ïg¥«={mkÑT&Ñþ3±N >B»CP2êGvL"Ì sØ:©RØn•_eÀá6‚áˆH§ £I›,g4R×ÃA瑺?„ßPz¥†ºíKóŒ'ÿ´Ž# 6^;ö]à—ÇuÄ$\‹L#ˆ0Ö×ç/~xKmøÚ{¤¥N—5 âò7{’„l˜ ͯgˆ ß)tºŽ9 ü¼¢]Õ¡/‚HèñÃÜSp˜º˜»ÿÙÖ‘xíEQ+N¿B’Áåª ÝX&‡M}A4ék_‚óý'<ôÃ6Ž[-ÑbÚñx88«#;™çÁº*û¾Àþã. .!:ÈÌŽìWÜו©4ìï¸sWGÑZ[K FâÚ Ðy¼HŒ¡I±Ì}Ÿ G ß°M¿33(²¹±Î yï’ˆò½²÷wDº¾£Çº‹Fú³dÓÈúYlÈ}3qÌÓÐ/ú’Ž·)gXÔÏ=·Òèá¢Ý¶¼x TAÍ Ä&ñWÕq‹¤3«€u˜èbû®4+å%ñÝc82ÒÖÙ-'0Oáû¸Ç`M´ ¬Ón7,ôØë‰¾Óþ‚o­w 3ßo22ÿ£²í‹Tñ#廊ƒ,e;yêÅèÚ[…={E;ÃÃP¸¾érØ„7Zÿ”æòkÙuº,¦°Ð:†,Œ¤@—ãLçÒiU!é~'ËNÂ:Óö¬JÁÈ€ž²µ`Ö˜‘œòÌÀ]û“‚êlÒè³)\ ;s‚Ä‹.‹0C­g„-äÓa¯¼'wÀØÐðÁ@tPð£z=y°º)£o–‘p˜WýÀ×E(Áä»t›kÚ¼ÀÝóNÅ«¹žµÇõ¥609°ß"=¸úT®X×’˜¤9Â!Wê‘y ´Ù†dýÁ¬5KI?îæ]}¿³ÞUãÙõ<„K«¶^bzÁS#O~OOÔà11‚àÓ÷L‰^)N¡iF‡ŠJwR+˰ê_*Úñ 9 ç,ø¹dˆ4…|qŸßI#CÜkJ}Û&k’¡—ŒNEøÊ³·^Òö¶f;×õz,…ì]WfMàKô .ñý÷2Ü‹ÄÙ‡"!órVŸ»|]6‘~§º‹ kLÃ÷úKÿ>î•/zͰ§âel†Vñ‘ræQ¨W¿(=m½ŸÅWꂉÂëYÇ‹u¡µ.« ·ÔäÔæŽ |Ó„ [ĉ„Ø×v?ËËuT}Êá /;~9‘û•¶_ìF¼–mïäÑÁ ˜¶¯¸6‰žŽÆ^F£Z2’y÷À°l,-Eqpw Aºª|i¬n|Ç'‘‘ȼ†—šÝz7ê_álj7a}ú‰.àå8]QŒV•ûÄãôǘjuëÒ,ã‰d!;ÔŠ1t;FÊü$éà {¶ü€¥~9H» Þk8¡Ñ¢î¢ Æ ¬tà¾BUiΛÎ3¤ŒÛ×,Cð‰èQe-—É… °b·Îp¾ö®lÆ¿”’XHXQН0( î~ÃÊ0F§1•03ßʣÿlz$¶¢Ö¤ž¤I€ö/g½ާî›Éqû4íl&>åR…ƒçTq/ZÛŽ"b>ÝÈJËea§ñëj’µ‰g´ÏÍ<„”Fj®Cç|b˜âR»¹ØåóqYðOsAr£»¤h9vá¾K‡Þð© nˆÔG…æk©‰IÒ}‚‹Ò+£|§]h:+±†ïh–l]RÂÐÈ«C ^IÄ‚§³ë=2׸_¾Èý±¢/L‚™ºþ|íÐ8˜/g¨eåpYÒ!(?Ú—ÕF¤„M¤æHOÓqúôF"÷€™®÷Ùla‹EC#æä´º:”VêøClK#P @ÃÑ`Öàïô^óAí¦Ø»O¿ ëÌœË}mòصô.ÜP䕆»áኖ?Æ10ƒ`HýÍnÉÐvÈnBŸ_îy#ÈÁæÖ~½ý´#°y„~“’¢«;)ì°¸c¾9N•¶Ií¼T@<ütss¿R ¸7 E™áþ‡1e Â@Œ*•ÙÑH𣠳Åì²îϨY÷@›v ¬åªœÓlžHò• XÃþÄHµ!²k¸Y3i—Ñ.û2x‰Ó}¼®þôû¶Ý}ß“CG7(‚sð4$©¬ÿ¾ïë~×÷seeüäøE…õCÄì) —ï6)i ww:Ÿ ½$Èûý7Y„ó°«=&—[kÆ=pGîºòá©@"Ɇ§ÛŽWûHBD«fíB{2)‰vªŸ†ív!j:6©úõ>N6˜gD•ºê[e¨|_°BË@Š›EÏ`*âLx¾N®#Xo1ë!q§±†PŽ”™T`MסÁ»ôÅ }—ôæÄ­^÷Ïòa–µÕöÍ©‹NCðsÔ'=,v>Ê÷ å¡.Ù“˜ ª'¬Ẕ»Wþ”Šx^ø‹šÓÞ¢üÓëJ¶2Ïñ¹¤™Ĝ˳Þ(ëeASÀaQåQ §›‚ár‡¾¾+}vTM­ ôÅ—$nê‰Î+v0P;%× e²›T),žd‹hÔïiH|íïÿè€u†ù@Ò¥ý`Ç1ðQWöÓœež|”ç‘Yi­eÿÎ<¬)Trz×O9’TÃôAòôgÔàž2\}õ˜$ê-\¤äNú:xâËkx]”È£‰¡SÅ"ZR¨b·%Yímñðz{õ“}è»òŠÚ'„ÝqOj¨PyK¹#’\w&9Ü—™C‚ÄŽœv~/ÖONž—/Rƒûupmÿòùçµ–-áix•.šL-bžã1j“OèxÉ¿§‘ûÃÛº›zº“€È]Î>™˜3U²@³Y °ÄQ‡ê;÷Ž„*Ó׎ëQ²>ÖÓ¢"¢ þlD>æ²’Msñlg7ÃÁ*æ5â/0ŠBºeø“Ÿ2zmÏ“º–[ "aų[·¾ÐÝÙl(eÞ[Aнfs#ß\©aü„±@̘’ü鹬%?z;*fßqF$&XÃäwß/·£ëk¦ªý(eë…K†?8]1÷EkzŸ¥Z‘üë,·ŒÔa.¨ô|³Cpç.„u¬*þò.2Lñ9U¥~»³ÌgÐϘFÃt¡m3¦´NÙâ7¨KÛVþê¬ê¦bVÂÏ$+‚ðF@7™«÷.̱T‹n@U»+½°çŠ·³*L‘|Tí"•jD[iy“/xØ÷])J#j~õ|»µÓä}†´êÐêÌ÷·¿sKˆ58}nü3*q¥M^lÈdÎÓ´‰6ýãˆEñ8žÒÓmuZw..þx—.<˜]Ýþ‘|‹fº Ý"-_ñ; ÛÁTXŸ$¹*ªC´l(P^Ñ9I2’já€ÚÔ,04É3™dÏÿÉM©BÍ‹.c×Þ I!aùEÓÿ¥Œ:Üšsåctó}{‰§Òvv®tÌ€x Æÿòq'‚Ç7L‚®'ôa2lD\ ·ö@9Þÿ½ ÙE ­³mz¥I¥aòÁ÷Á2 ê€}Ns5jÿÑP”kËΔK¢COÈûš£k?Y’Z5:ò2sëÞS/[Uç8QŸeûµTN“гDw7ZŠî»þIõ¥lñ7S[bNئ:¡jÇ&hÜT¯­‡S½[ØTéå+ÔÚÑN\ïӠϘ;®@޼/¸ëÚ¦Z”ÑB¼_i¡“‹» ‡#^Y¢àÊ%¼VÆKƒÕ`O,3«Žeu/GLGLocyÁW©”œVqá¼q5¯x³EÙn8<Ó[“Ó M‘ ‚Lš/ÀmîÀïFaÇ^ø†#‚´÷äW}gBMŒ®qªrnOä ú~ oOܹ­ONF›ï#Ó饯$9<¤þ…„wH4(Lèê|ÖÃP«Æª½!­[ ¦ÃE+>Ï×Ñ$‡ÉñÎÞ~TܤïWJÉßáN²J?Æâw8´ Ëü=íqÆ;Ъºç0WüX›>·ON#¶Œ£él-˜ËÃt× k¼”v–š._°‘¿…È—OäA2Õl˜ìúÕ³“ü|°$µ¦K©CÐ#X¿ôì=!’¼+æ‹!ÿñ-'p{S÷ÄIl•÷þÙ?6q©ØÌjUax¬É²0g¼®Ò@G_ˆ®Ù€9ÇَØ\”Ã~äÔ‘ ÔËv§»ÐqH¸Ô!w4§$yæ ëgÂÈ&lÒk$yC¯k´P—-´M@6i8YâAÂÌYÖý!úÐ?x•1Li·×%'g0‘ U4G…¶CÁËæã¹Ç7jå#c1þ:À¹jy¾ˆ@ÎÇT$íš]{F¤Œ8ÚijÜãEKê«xêÆÈü’ ±@¼f=2_gRŽ´$±®A\?wÜn.L 7 â×JØ4ÿøÞ¿‡bÜÕPíµ±òmøS¦íPªÃEBKÄÊImi:ïª]t[8Ç¿ð½áÜ/Q‹ÏùKéLkCc.#ì(Ì®“KÎ?Uƒ¹Ñ9ÈOGäòS3ãìqkFY%‹åÇÍ‡Õ xõ„ÍF¬¬ øuÝÇ¢®dÿÑG¿VæzÞ¶#*”ôî±OŽr¦F¡®Ù vÊ<ޱ{H~Å-Ç\Ù´ÃiÒÖVÓ£ñOBGçlªm×$vq*3Hë,·!é.kAÒVvF¸é§b&èÏDÎ…5gŒŠú°¥(l¾Þý:e¶‡ SÇ“H±œ»çl—küS>ÓjóóÅ‹µ¦Hì~r˜wˆŒÅಚO§æEÆ"ÒÂŽwaNpQ)L“Áà¡‚$±!i„$åB$Ã=ë8PdÊižÑ)A6••/>Œë¯¶úŠõ.>"|°hQg1äQ§ÂU1š†;øçQ³rRÙ£S[Ýàà‹r.úÛ$Wè/|¿ZH>ŽìC™3 Dë`¼šoˆa¥D“zjmÔìèÅè_Çá[‘âäIÇi §Ã†¦¥K¤&/–‰Íb5D‹Ù_‘>1Q²OyÆ;"‚Ÿ¥ÖmÉÕm¯æ 8ÝÁ²ž¶éÇqnNn”ú;ûÐåÝ9o¿9ZŒ˜R¦[1û(Ypœ°ë¤ê³‘¢M›±jëÌ´ÅûŠgaW‘â][¹BåùÓM•qi£F}]…»™‘ïG0}˜Çû%:û¦ø¤Æ¸™Ùp€„9\ u‡¶øô‡M îu‡8©¢S>”¶3ÜW|ÄÝç7 ˜ÇÝ*: 1Ú©Ù¥Žl¯¶¡âJ~Ö|a=«9«(ß-ÐÇèÌÛ¿^Wú\䣌·q<÷r±]¼û²´árì•‹I.Êÿ| t„'ÍëzÃÞÛJ oez!±¶ù”œªÒTR&~áe4½¦Ön?ÿxa‘8FX«L2’z+2!T}ÔuÿšeiG7´ââY‡¨XM&îðÃŽìUJêœÿýîa¶ì:ýw ù‰bÒÃÜÅ5Í6Xî…ðéÒǺWôº]žæ‚SM§s§¡æûoâ¥lª“IU‰³8‘ý±I8ÖV‚ƒŸÈ¢þp œ–Љӣ¬éf%wÚeŠ ª¿ýÎL‰x4ö_×Ù‚(…ÿx?‹£\Ç kXXé Fä~ z‹þ)Aˆk‘å²¹Ö2T¿QtϾ¨íŸòÀ²2âîù•ð€rP¨V” >Ï”£ä«!C‚g¯.'/Bß@þ ÷OS´eS8âžû¡mAðy3Ì{Æ;êI§³QÈ8·Ñjç¹oª~U”±ói­?ÑÑý  â5/¡Bðþ9Åær ä·=zØÉ[ÓW£¢Í­h»2L]´ï÷º2gqƒÛxN}úœT/FEßìwUíØ¹¼:ß_P ¨úf'sFìDWÁî°ú4êã•ôß=‰’”;6:»5äòiç³4º™Ü#°a€°&¢ÚS÷Š?"µvÞwg"=‰èÍœaL ÂæÜè3Ò©æö0LèLag›véBßcnÏôÍ^Rh÷Äç•dÃ8M3œ½¡ÌVQ#ÁªÞn?Þ(ž—6¢/”Dó ¿»è3¾ƒ†sÍCù`×:åo{Ii@,$rò‚4Håy}ÕO¹$6ì‡òY¦é»°‚b0¢½UC'ˆ' ÉÞŒIhyMÚ@fÚÙNrz½ ŒahT0Þ뚘5hrC¨Ñ–¨”_mbŒ˜tÉP³[ð¦,‚÷#tÍ…ˆÊ¯Öú e&*ò .•žÌÁQÈ'Oá»_ŸG¾6ºUDW{æ¾Q˜eÔT5Z¤ï”²56ðí¶˜$lÆÑfåe©V™„NP¢ÌQÛS~Ž’Òölâ6ÍèÅ»‘ƒÝ^@à6~Л?Ðó,‰Þ5º^¹úøbÀ,m ÁñÒÙþ(l4q“o`ä´Ôk”‚ðƒ†»Ý‡Î¨S Sö¥áqŸ qx'jrfÄÖy¸-)õBècxëǸ´™wbà »6K†G ¹ÊËfœÍVC/ äq˜¥îîx^ºmŸ³DZò'²LûÌE@`=¹tÓÙ]Â%’pü&´¨¥Tÿ圮zGØ‘Ng=w]#Â:vá­Õ õ2bDÂðm t<´ÙȹíE« ¹±ÅV:ÑÜ<¶cú* 77뗊͉™™ÏÓd¾z(ËP[£“ ܨˆŒ$+ WéËù—ÌÄfÙ´‡ß7J;0=ÑkºHªNÄÛzÂÀ9ñaÙHK{÷e‡7¾“‰Ö ™;¢»@‚ µ—Í®‡]xg;„a…â³RäîÌÜ:?©R:m…¤V¼~8-oÓ·Z³ðö5˜TW´¸Åèfî꽺ą\wùÏ ƒ—]cWÅ2šVq-ŠP·DŽïE,Æ$Cº;ž±óª…6 åo®Œ0"LútevùÍ÷¿w ¶›\ïéÔ‰-™¹)ÿô8ÕÛôê†ÒAËëðä08¶ƒÔ׆Ë_ßÜ?md{ÔÇNˆ ™ÍÆšÞæg'Ø%‚Ö ›‚Ó'~)…èÜ‹²šwÝ÷]Š6ОWGâÜ2‘G>xZÒñ,Ì%cE¤jôÑ‚µdFÜãÀI»Á¦:Ìÿ k¯ÐÉ€;,Á‡l8âÉx» á9Ä­}án’æFGï®;†nNoÝÍž“2•@ Àʹµt«+8ŽW= ïàBz -1+†aøU¾x¤`ÙÖQG0Î+Æ7»3WœÔR*ö½¦äu6•Ó 7¨ÀmßU•’ ;WçÊU‹Í ÄN¿Êc 5Ÿ2“ø(G” åûj÷*E}>oaù¨br}9Þmkù¼ "ÇÈÞ¾@ïÔP9ÓrZyoë’o"ŸÁ0ünH™ž4ÖãJðþ•æG8"273ÒiÉæ'sÄŒñ8N¯!xT•ãwFm1RƤ–¡˜›BX³ QáÛ×àŽ¢Ñ=2X o¼ÇÇQ(:¯ê7 ~ÑÛÂÐó–™b•¯R¡hµWŠ>š;ò¶>ùF©kXμõï‘‚e?»Û˜¨… ¢ÿý/\X`¥[L©hü§P°¼¶‚„'¨ˆ{½çèçQB<[J¤'8CTÛ1g²ÏÁ#{9o¾i‚3“3q¬H êrµ"Á‘Œð·­ ÝJ‹‰v÷ÔÚÏ“»(ÅÅxAüýòÀÅN;£ñÇË­UÐÒóÊ%û¸R 0Q¹tÇÉ’ JðM–¤ÎYš½œ½à9$Œã:e¨½V™ágóòÌñ±Ò}é ŸÅ!Í/—عóoÏ­ ëSQ3Ú Wßðú¼è,{ó«bY¹ÈWùP¼ŸßÀmˈºŽioIo//¡PU´1 )oC¼?-Áa$p]«î.÷•SVÿRãøÁÖME¢Ï¯S£š³£MØir¢˜¡»©/)]Úô”‚>·(§ â¢U$ùSÄïÁ]¦Û(Z0ºù}ÒH“ƒ¿EQþõM bʪ^P4¹1Ž•ìª‚pu‘w½CïÕçäL(g:«•©r›~%ë'jH%uÿT$"*øÉ¸š d0HZr8ý_ÂÑ2}¤=Yü?ÐxwCó«Â  ‡Q6ê>¯+˜â!s¡k/j¬^óB¹µ1;Õï¡B,ç{°Ç¯˜IÐEHV<&/'®av¯ ÞÐß&kæ …F7_`u!§}ì’·ÖiîO›®6û* –€ J³d½q‚2Ù ýçkKT•ÒU\gÝqôï$^ò#ì¡MKÃj°°(AŽ28:>ã=!AÍ:ƒÞ°PÜ3ŽàIýz`~p¾eŠ>ÆzOöÃåßéçÌ»…8}Nc½Î²íX«dä¶Ín§¥–¼4Œ!dÏ„×äz&Wã@¯UPÿÌB¶ŒF“8gvÛ[š»,lœÔÙÛíWõÓØ|ÜU-) r;DÜV£‘¤ýS!õèèÊrØ7l#õEg°12¾> &Bz–Úßmåå=ËÃÔãìÆ‚í‡ÚI›©,G —´tÚÓ«†bjé^£#·Ÿ¨“–zÚË×r–вå•W(—f¼ÎÐfH#Õ>‰Kà©Ë°S¿?ŒâÍ]j_íƒÔ.gšø˜wnE*îO€óçŠ$ìPšl{¦mÿ­+á8E&¯^¯Éµ¢sÑCkþ'³]S|äÅœ9o}íïTy[»§œèÙ*Ü÷Ï…1‘:â­_èí)ó¸|ë/׉Ú“Fðçèþ!¡Õ4Dö¸ðm$ñí\Ç-œyÝKL;|\6a/š¶?äŸd´íK¥¹ÒBâF/i¬cu^(F •{’ÑÔïQ¡üƒW§3åÙ¬€êãOXkš¬jˆÏ¾Áµ`7– â{7­ Ê6ýœ–ß;Rë£þzw\ zb41Û¿AÔÇ‹“T^Rö+z–!Uý[æëÉ)Úì‡JA± ºBxÖ¼:$¸ôUŒ}{¤µí‘ wý@ÍB [Ä-xæÄÝ#†i4Ö;§xj_¾_ŽfHvf ÂæTÊß`çhkh+Éä|"”Y€)X²š4vß:ÅTÙ §+ÄC:•5Z¿bšÄg»©çö¿Sžò+òg2ÓC'’úÅUô(!hg²‰“RÝ^Ù#6£ÏtŽ•ï.⡲”²þ¼Ú)|«q„rÉ%nå‹Mö#j+ÀÃ>ÉA‚˜rõ„xÓF˜‘ç¹÷¯;xÃz0ÙèeŠì€ÛX½ÜXüó僧ã\›@à,–œ±åî á«‹IC˜îEåã¸vçÛŒC-® „¿5°åÅ”PrÍþno·EJ8øýãE§iaWNk0Ý w⻩ÌëŠí„}õÜ®ú2š²ÐÔáÔçÁ> m©Zþ+³HÐ!î‡cúíS9äùÚÃp\Ýô´¬ú·ƒÏdG:/Åù¼¿û¢\ž²(~œ_ `Ó¥y‹z±Å(ÜfÖ¥ÚãÁ"~*)ûíÞË{.“½í‹¶ô}g}€¤›Ldé…l&AuÂ_Î ®˜·q™{ÕöB0 ®Ð#Í\õ×õ°DR¹QPB/Ç{÷€R$8¾ÂÐIÖa5=Þá¬&RT×Å=ˆ?ìö—ƒÉ>c#¥Jœ\ä,*½ßî*~'ºã •|¤®Ë‘Ž'9Ø€ŒÌ»X¥kÆ{EK1ŒÆü¹‹ÞŠèOeßHÑФ¬&¾­~‚i9ÌBù6ú)ÑEOʸUMH}j'Ä †ðq0‘L6üÀúr8;`9µ¤k÷Aat*o” ©X?Qߥ!AÁÒÒù›G÷M[UɆËòû"X Ë~•˜Ÿ jÅÏÎâ›d¾Þê›®÷ºËúµÂ=®3…F‘««”c_9™g|_™lЬŒS!½ìñý[!¶Øž¬~û >^}ÙÉ~¡T‰Rå¯N´L¯«ö…Iª‰šîg;Ÿ©£â±©fï›ÅH–kÒnç²òÿ»­ JÈi—xuýãdgé³X˜>*K )UtŠ“Ìð#¥$D#AÕï ù£î|Ãø"*!È*àð±É±°<×o·õ´5üwm+ë’~å{I·¡v°°{¹Ç«û¼[½z–ù* [mY/à5ý=e&PòmÝY&w;&[jA”>Ä}Á—Òœ˜Ì} 0‰š l~ ”Œ"²‡>Ù\9 ™…æxÝ7…|ô"E O‰X3Rvh½k䢢LÎæ¯¬>p†Z’Ò¯½6 ÖX8Jô#ùc9¨Y`µ (Iá!C“{(§f„üšzر¼z¬ìžŠ½‰_ädð!D~Êð°ÎUcìž'rŒÖPkD<‚é÷d³xF íÇnÇŒÖÌÏ£€g›$ßßrEñ«¥¸–7ÞÃMƒïAÇ{|Á|¬¥œF4¼pÃ\ò™×%¸=zªÐ˜’ǵOG{ó»JM¦S¹1Pí:‹²ÃÃŒ‚HˆBˆ´Z\»°ªä:£œŸ”ܾƒÔH瀺é¼%¾ÿ G³»¹}F¬­´d(E ÙÔ Fô-³ÝÙÑo~£o²™àókÊP·?Åû(f&©ÛahiÐz±NXÃì{ÔôI+‡Žsn4¤rq< DÖ¹÷> ~¥³õEÅê„SÃz}@.åËò¹[û#¿VjRH;‘E¼\„2°´ª"tÆý»ùvÑú[è»âå;¿ÍÉcNjåzà{Á4Œ(²[·?>vCü£©ˆ ƒi›úêpA¼rÇÀš‚ÜÜÏCÛÙ„õ·Ë¥)a#ðK"Åþy{ì?·Ž¢T—4å³4Yp ÔïL!¥³bÅÿP'QÆèX“¦Ü¼vH[ퟦ 'ÓsqÞîmO÷W°·ù"$7wŸ^Ÿ¶ »qÃlùf X¬HV­ó~ÍXZuV¡‰€·—tå¬`Ùž`cH¼Å½ [íש.¡·”Ó“Qs'ìáÕ£p¬kª+Ç«ˆ0}0WÓM|ã[9ѨÍÉ@ä1Iebúr®˜~¸qâi}]ÝgJì‚Îñ€¼‘S×Qt_ 0Ó8Nµø}Ôˆcl"µõèÖ¾Nœ ¥Î©°Óð–U¨6(CÖ×?tlç I^·¨æ½ãJ8¢¡ù`Fš‹Ÿ0<‡4!»Y3Ê‹|«È¬XÄ7 ®¨ÿè{^b) È’ h|i±µêÎ y8\’|ÇÃGÞŸø–þôã´úµÐy9ÕÎRŒsù¥PÉ„²Äj‹Wò›«ßBÉòPö~º^øÙfž<ÜÌHq†­}û´rû|.I‘.ŸrNŠ:ç¹"yàò|Ø0Ù³NPY‹µ&t?;â–CœšY—×™BP‹É“’:ºkÆNîØÆ›è¹ÃWIº7°±iýØ}›Àð¥Ä@øeþ5Uc½˜5ã‰ý&{Ö÷ï’¡hÃŒœíhY…¸¿\êƒùš^‡;$Wn-K0ÿ`wqÏí °$äÚl/¾H 1ʺ~Þ䱡Ê;Ê0_I.e¦éWuGƒ‹{áÕD2ßÚ~¸Ü×׃>:šY;* "Ðè/¹¥æœ·¥4åi§âò¸ý }˜ƒ(À¢vZ7Dqµ°h¬-úÈŸ[½(”ë¤ N¶NVêö`èr&ú.¦³Ôp‚»É>3¤*| ¼ŸÍÆSKÍmÑ9Ÿ€k2+®¿½fxO!^ËÆCŽpð™VùG+ÆDéÀÉMlœÂ\„ !;ß½îÌMmÏOÝÐeÜ+i 5¶3®J?i<ÊœYFóå@ÀãdJ‰Ò]ùÞʃ+>9 ßÀ#ä„l59.\™„}ÊÖ¹ h{ÉΪ8wT@ŽöÆv¶ÚK¯Oüõç<ʉÉÓÞè‚Ì‘mx†~ºãjô XGà7‰¨×ït‚¹fŸÐ¥‹äCã±axÝV#zŽV–MgŒÚžô1ÎMS­]sFí:®¥³-äEÅPíaËŒªL[dó.”h P7o¬Øökr )ø¿02V¬|¾U\M•X{ßPœvn ì.ZßâÇ#²!-UN¿Úa&MÑ8Ë%Â6£X½2– „.ß&†tú±;Ÿ$?д¬É1 hßfƒ×lýzq õ~¼=Ù–Œ-ˆó0¡mÑC†ÈGFrTzÄ®|ø0gÍT¼‹-Ôî‚J‡ÚÒUÛ g*ØÜî%‚€g¯Ÿ4Š×ýÅýzÐK'‚XSÑ/gØCS$¤TW›AéPÏ!cE6™ña|ãÀ4²ZÎô‰å~Šé¸˜£¡Ù†.Q­òž”¤YŠ_ S qF$OR ʪ@öžˆÙ³ß)!=½`Îj@Ætl8B l$`©Â¯ã³g¢$ºÙ/YûcbË{§¨ › `7)w´¾€ùnQ™À]ÎÏ*{cšI™Ñ‰'cDI`¶Žñçæ‹,¶ÏCͪ<\ò«”ÓûTXy}|ˆ„Z®BûqXN[v üh˜ù;Õ]i‘ì»âmoF ªÝ¬á긆+á–;>8¡êŒ—Nb%‹›d8&£~ä¡0¹Y‘wõ8´®^–-!šÓÅÉ'8kŦ4_9Í£Êçøâ4Hú™åÖöȈº{§-{)iJ4áˆþJËxl5I©Õ5àLÿ'@Ø¿ýÙá-BÌ…Q’÷pH®ry23ŽñüÚå-6"èó÷T§‰¨°ç˜¹‚²;äHÛ>[òšù+W— ±ùÕÒ—ëíßbKçdñ€ù@(õ:Qöà3ç›j€Û+;ã7I_%Û¾Üô¬ÔM‹ª¿aVÈ+‘T¼Œ$„œŸ‰žèküb÷`¨ÎSþâ~ó °¤’Ûö‰·bÙ¯+ÿ’µKêÝ‘ 1W§ëÛÊ»zuóE`°eLÕ9–d!ÙŸr›äzSN¬0³Ñ‘!Z Imç¹³‹[ÒR­èxMéFËk°¦OÐ|mË1몗žCžû1“ [D¹Ï³5'Ýñ8“¯´UùT mWÊPÜ?(ÔÚåÙ‡•mˆ© k}•ÈòôÌ<ÏyeÆYü¤ÒáÆøL#²ÜÁ‡'Üü»wb¹jžJÍÅüJ†²ˆy Ñ,]è¢NÙÇP° ˆ7Vx(u`îJ1õ×¾¾¦¾£žèX˻ನXÒ–[z• CøŒ7ýsÄÐÀaÒõ§™ÍÿäÏC.”¤? å@-Å:`VÅO×ÞÀ}+ð°·òyóÏ…@#¨H ljš$P–¯‚ÛµáŽ4TQ?ä8þAìmá9[@„EÛyÀ%\€òêMHËÇmc³)ü&‚¡Ñjigi,ýÐw úcl#Sê³Ç›ªïÒC†–üÛ¬IÒæl»K¸|QDbÃmÊÐê¨v(Ý(–ž›¿í~ýh£m”„âÎó€XjBʵ’=æó()úè}Áùsüéz:õ¾*c@ ÍBH±Z—³Kðexé±wà©kÄw¹DÏÃ~9F>´1‚,‚f¸Ûp‘Oï>æßi¬Pôu_k÷ôböã‹j)øéš8ÒH,FÎI'ý -%_°|‘T¯¦ï0Ê[õ§ ¹ ü!7mÏÈC0#îbMkXÔÔCfÒZ]Vr\t¡Ÿ·ç€ª`ÑœìÕ~6#B© Äå rÅ<èiçPõQªÉ4cÌ‹¡’Àº³ð—~}™]] _~wV]^O‚ܰ)¥ ïÑØ¨ö0«?äÉ)V AR®}\£$¤Û dÈóm˳˜£²Ðw8Jˆ+\²ž‘‘UßMÄG£Lî`„5móèªú(€‡?l¼§˜úwñšŒh›%ÿUŸ•¶!Ú³Ömí`™SZMÍT¿¨â¹JÄ!ݼ—›¾TÜÌ•ÏRêî½ËÍ$ó¼ÖqsÓ}@¹r5( \©+÷Þ‘q:›?ê+áY€¿ÔIŠp±š'“Zy‹ìÛ0o–?á¸ówG0¯™“4 |ôm§Va³Þ!¹“«å“‡<±­MÐC„ޤe‘ÏÚE3xæ¼»¢¥¥Á0®qÈÚǾ(A`¶sÌ‘ˆ•âtìÕ› „nsSt}=ÆQ´Ò®] Òþͨ©ÿ]¥#¡n€UV½"(fÑ›y¸-Q.nEö\ûrá*¹¥uv®@èzñEµ¿ÔÅ×­8(g!Êä?I7¶˜ÃÛ Z™sÉ@±‰iáÆê¢IЩ”h uŒE’v=šzu3*-êÌOݬ.Ë;Ë,[ÁÝýîôü^€¡¥Ñ=`Ȭ’aÔ©I,U¤>ÌX–W‹ë üÿ„qÏ]{Sj9oYh£Š.j¨{·TÝ€V䉱@wû£q‰–jÒ#ÕµÝ9•oêc÷§›%¼;ÂÓÙ²»|EdŒcP_~¼BŒ¯ü;g“a™òÿ¨#¨î'sŽ_ßœ$|Ñ3ýÒÕ]× R* ”tL‚N) ”[H>ˆ†P|v–K\"Y!³ì°NµÎM¤¹NÖ’;ÄAQ‚ôR1ÝÞ61/é[–VãL!èæ"vBƒ§æ{çd»—Q#<9àdAOÉd–ü‘ މ0Sás9ë쩌øÐìÆäJO #‘:R\È#ç*|/’‚ÒÞ€‰Ÿ«Ø©Ïi†GkQ ¯±ËnÞ=!¬n»j` <›—´²©DŒT¾MzË'=gåL™‹úÙ⣊㶦}ƽ€¼-ÈŸ.^NQ›™Îidr!pH>ôK!kØ¥8gU`b³ÆòÁ䯲.üÂXÞDk å¸O8}eYzI^%àâÕlìŠÖ³D‘ß4×!ï]ý\˜OQ›ìÛŒôÿöz›æ·Å€õ`[(eU–!O·W|÷¿+ÔÀÀ}Xö­5³E¾òˆvÎ/´‰’CÝ©V˜°³Ú9~~y'Q®Ô=&ž /%1¥U'šÖ828ö »Mdº6Ö+†'=6ºt6ÃxõÝUÏ3öÊ"J µYÂTm ï|t *3zõtP6<‚÷Â&¶yV[}÷Okëf›õ²ñÇxvZyêòí€â³ â$EU‡³ã`sõ!PŒêà­–#Pðyþ5y覴÷,³OVþ% " ª×â'cbÔÄUiYpêÖ™BáKàš,ûÏ °©CEDå £nñ°£Š ûÊîÀû?;rÄÉ«öàxÂ3–Dd GµÆ. aÓß*@_b£ô!m*©`ûßP›ã†’ Ëò¢ÈqºÉ^(½DM–#Gp-J#ï,ÞȹÃS„Lf Yó”ñ3­nê,Ž3_ù’ή1˜Ô6ÉèömÑó[tƱ㞑0jlGcŒÏû!ËÐ8>Ƀg좆+ )*%]~ýÁ­†®•ˆfâ,93§ù ‹è =Ô»2ã0ŒúžXìRéÔœèý .óñŽ¢ÂX9/^ÛØá„füo*R&ÿ‚9UîÂFgW¦N£†™ƒ+6[{B‰jEהΛ«“–(á7†{YºÙ)ããå%O@v¢‰Þ¡°Û˜9Ù“i­ ~5h]*äKÏbO]«Å¶§—ïiÁy¯_æÁFVÐ,ÀÓ›T=+ÇjÃöe~r—8(r jçÅxª= ’±•„†”4ªÎSçlÀ|;>­øŠwÛº "¥×TÞTR[“|¾™‹ºÐ$İE¨pà:t@i 4:‚¬±ò-e:ßm -HÆ­Yš*•¨yZw/ZNPðÃì:µò=RƒYóÂhÞü“x Y¸µãá ËSþ1ÊÕoø!ÿÉ (¥ì_ÿ䣘tLч¹c<Ù‹ØÕ¡4¾ÒýðmëÜÝjºtV¯„X€¡èU<Œ Æz‘FEFÆüà´ýkÊw„+ Ì-*n=׬<¦l"‹ú§¾7è•Ì-»sëRu†ï§uï0Ñ?é£6/¼ñ–}¨¹b¾ðXƒÕq@ÅU™ƒ¤6.ž»ì¹ÃIÒ«k:Ôk*6Þ/‹üx.Þu á(jMl)+FÌ[¥/ò|g:iXxª¹y+(Ü›çá,¼H.Œ,ñ‘Í„R> íS‹Å|OÙ_æ2õàYìKO¬>T†"£y.EQÝø!)Í·À–˜Ã;é3³øhN«@wæzAä¬QwX¬?q¾²½Ò%l#/‰sÆÀ`²¸QÜÄ6¬ñxó*øÆR‰×¢•úØ9¦èËÃŒ7\'FȈuå´­Gç6îNÒ¥]}á à.2 };ögÁý".OeE!}VW‘ äšÒ^øà!ð[+ÍÄ8ý+˺K ºøg¢Þ÷`}}Mxh}4·1ïñíä®ð@Kñ¯‘¿úû·ŒfôñÉIf~1VT\9iÔ€¼ïé‹cØŸu_ÇOÊóņG{~bƒua"h·M†<ÁË^åËèH?WøÃEW,]×&Mí¾WpæÂ¦PWŸN2Fü7Ö>—â‘—Ûª:¦elÏÇé˜;ßïÎC܃ó‚bö:†iöé$×ðÔ%¼K JŒ¸;DÆlÅ—ýjÎ:ú Ý?>É<óT*5Ž ‚×1Õ · ‚óL2“TžR;2¡–O$PÑ–Õb H~Ì­¥°" É$îD¤Ñ›—³z%0ï_x%¬Kœ¼,µe “ï0ŸV®¸ï5œÆ…\µNáÃWàZ8mh¿ª53Kô…Õ‚ƒ »OQš«Jd­uŠ4H¯€‘ZÒÊçäÿ¼©ˆõÀh†èï:¼“L.‡Ï ö°ax‡_ƒÏ•œœL$ÆÍÛnÜr·¸¤óhV>:òh“ØèǸY‹Âð9pš®§þNc{E›IùÄœ¼ù–uÔ ÷T:jghwCUMCiE÷R›Ž¥ZЇñ‹ ÖCí1Gì%*Þ¨æ4z×Qºâ×Ìψ<[œˆ ‹‚¬õ=‰¤MÔ¸¡ðƒy’*cwVÏš´¶ PU"A’ºòñß.â(Ûd§Eœ(9eVÙøç güK|Öì[²¨»‘‹” ªK£ii¢š3Ÿ™#Õ µ„×YÙ À iÑL»X3ŸUál{ˆ“Ðßê),Œœbƒ¶›rM²Ðc ¾¼ÁœsùL±^”ì)Ä –ìOä±GcXJóýg®±zp°iÔÝÅÙEšÁ©Àr³‹ Ýæî]hÐFáMÆ^™Ô*vO´ß·<Òb¨}d¬ü!»´Í…(O÷°ˆå@¬¯n×Ý•|TWÝñ+gôHu‰ªís3s±5¼¦“ˆ6t-þËâºh!ô+ «¶ÓòŽ×; bsêºÇ·Ã§U6-?gŠBöÜè¬Þ ÅoÓÙÖIñÔ©nb¦HKºGÜ‹£Ü~܇cÑb<ùSûD3jn|¢[ESY—8†€ ÷û¶¼fŽ9Þl¯9´½W›ßàä]¯ðCØàn|®q?Ñ.ÓèGìOÔè(ŽªTZ&éŲçžïZÐòßklyÝ/LãNDæ[ ÆžU;X“+æ÷.LqzþCÊ%Þ†ŸëN L˜ç Ö„”9¬½øúZ>G”ôþuÐÃ¥øÍß\eŸ²Ø_&îöÁ ®ìÁ.üZdèÅxz,n€ ? —˜4á Œ>Ü­GñPi,xU&}5+h"Qì+•Àí+\Ãpr\Wg/5:Œ-wRoïß}€~!þXô'xéÎ0Xï[*þ²€Ó°~Ð}a³ð¶Oª'Þß¿©tÍÆÇ;£³ÉÊÑ霵ne'Ú¼U½qh–WVwËٮ€Åņ?Xtɦ،Ó@,õÈ”¬×n}5|Ž%E.¦¶ÉÙ`4´)v‰dlæSêÙû*Ê™÷¯ç×-—»“wżâåïO³±6þm©ÞrykÅÎy"°ý|òk¡€RéØp—V ÊA«÷©‘ÿ>R\iQ jŽ‚ãœo–h“9òÚÓÀͦx}hÐDÇ£ óL\ áÁrˆ–ª‚ñ¥3ãÄcJêP6iacœQï*JLM•¯ú¥êèóŰ#·éi9¼÷cÃŒ–ãŠVð,ªu/{>ÅÉiJ,¡¶16Û‚&g¶š%šMæü¥'èçgdò¨‹[úwŽ îçÀÀmZõ•Hû:(ËDjôrØU—o½_Å•#´}m“ñ“6éäf£¢ÅÆýXH¬ëQã@*A: ·›œ4Äÿ Åá^/sDžtosqÄÛêyF\‘iï© =ÑóË8IN ’Ï#”1b_6ÆÊØÑ$GÓY6ÎCþÖ¼Ýðý20ËuÎ,¥ÀI’ªÆ ¡<áÍúeiŸ‡?ÅÓ•øéO¨kO wª¾ ë(¹›.P²·‡ çk‰¨•1@£ƒÑêLnº/‚(`<™ƒ|G¤+äÐ:oÃútK¾0´ Ò‘¯YîòË},Z拇¯‹Lk.êÝÎt#Ï{8wâv¬Åã2ùï kžë¥áJóÙN[^¼6o^(ÍTN:î¸vzø2$ÚÛ„4<;¦.„ ¦÷lÖâ|yŒGQqì +¦HÎsÇ{ý'_jsíǘè1ë˽5ñ½`mN©šJ‡«¼~só£¸/ƒl‚…oêl¤jÁH]dËñ'“MϘ¨pÁ|2¿±#IÌ·³z§2{ ÄÎP¯RÉxFÀ²¬x[".]᾵îWSì3óìþ¯“³VÝ És=&[µPÇœ Œð'N§íOvÚûkʆ?2à´v›çô›ÖRk›[£îŽº-;Ó=«>?é†ymD1sÊ`«–Ú9ñêÏVæ1SŒÚò €\óÌ ­DõF1Ôí~׿xA!¢Û^;å¡p1\9Q£ÈƒÓJü4uõ^ÑqEÛóÛ²ž ½’oÝ#%„)¾RöF%Eºýƒn[bEà]ûÀòªÊ²5SEØþ¨¼ØžßÖ#øIª ÚùƒëÜ3 ¿¦}ù¶J aAÄh¡-Ôà)$"Áluê"âÁ¢9¤?år 2;ŒŽö‡WçØ´ô¿Q[Üž|d=ýièȺó‰ÿ ò…õóc¥“¯X¹Ã¤80¸¬Íy?âpýÞBÉ–íÍŽO0d«Àwéã)ÀjS¨æBJÅ©ç>jÕn uÜ‚ô#áo§Ù®œatûÌܵv@ãÛlî]u¥¨ñÇyp×·l{!YÌQÍŒo¿³bj mcv*›ò`hôS?) Í½Eúƒ œ×ÏÓn´|ä¡ét¡Ö®`8ÔË&×ñùÞ"cËb cÙüYpsÊÃ’å `O{îâ ž±îsµÊ³27‘!fÚãöXWg:=%ÅôqY̸QÆ1Ööœ¢W"Ôä;$6ëÊzÝ÷ã°×oò¡ç͵r²WhgÚ 80Oç¾g&þR­Á‚\íï6o/7Ô×/¶ÅË]K£oøâëÝìć­_ ¢ 3ÿ )zU=¹º›-ŠÃ]Ñ ‡…?´¾‡rA%&éjÕšâP“l¸‹w:ºMѹXÿB8ËOè$J0Ù„|6Õeß÷F%åF9É,šÎ›%øå¸\㾆ÙϾ«‰‰ËîvOßB”âH¾ùöA€bà†L Ý"´BÀörZx1@=&Ï;3hq*§éj‘–ï^ú<®c oï•li/aU ºyÛ$xë1gÕt«Áj1ÂÍðXþbNݱ¼µÚµ «Ä:¸ ¥´uÿ )Þná|oªà>¥<µÓIwlg-Ó,[ ™•¿ƒVôà ߈ËkóhS±³)øP˜YK{…0»—ç碌¬þO÷e+Ñ:Ž¥­Œ#l/z‘ –”a âG€œ%I±'WP—×W}”| TznrâߤiA¹é¤óí“y*,¢åü§Jû#dIÒôÞ¯fìù)1ÇV4a]ªòg ·|™CC‰é¸ÑfÝ‹ÿ[$×\«V]ð®÷î½F’§rà³ÿĦ9ÔWaâ7 L"Û &ê†Ñ·£™ÿV.OÈË>’”îû^žkÆi°<’ú°0~O¡3ÁêÊ+©ú*k›Á>°§Oô&—ƒ¥‘_©ÓŸþárö>tvÞjP#ê»ý‹£×Òx©i¥úh yt•­{#¶e2G“±—f€u/e\|£ú~ë—>¢¼âp‘%7™¦šIÙžæ2Ë ¬Tÿï ‹%:33¬æH…:§Ì\ ÕŸÊ® -Í£Þ¼‘9€ ºßU˜^„ÔïÙÁÇtOBظwã:_—CË<.YMÓJ.ÁõÅÇròQpv‚U™gMÐ4ÕÙ8à^ÎÇ`5Ey¨”ß¿`;c²÷PÝ2P%©é-Í3cç!Ù)çÖߊÄû›b4x£ÊÕ²Ðy»'(•Ü@ˆzXŠQkÝç€ìÛ0ˆÚÛöôžÚŽÞ멉­Ð‘O]6¤3}‡pš¢ƒ¨D]há¯÷x.¸]ëˆTíÅê(²¥MiØÙf%‘'§T2µ 1Àjò_÷ýh•ý·TdèÁQ÷‚ºšÛf‹ì¾& – ÖÔÁß_!É&É­CÃV,‘žò§H½è¹'Ém˜µÜŸ4p‚€ç6“ˆ$§Š>*U=¸ÞÐÞf;É ÖíÓÎæódH#¡)Öâz0ûpgNH:šÉy„y”¨u¬¾E*­€Œª1ÂÍðXþbNݶ#’pþ?ò•|”jb>×ýÑÇš¤ÞgR@¨t…}ÆÝg`Ê¥… ÈóŽìRncÇ8uÉÇËó«L!elðt\«@hËán2щ¶0Ô@ƘCTKZ…  Ýü/ÞÚaªôyÆl~ |t”{ó:{Y÷*j‘‰dr³„Á¦›K¨¢jžJ1€§ee+½<$Và°~¹„’o\_5¸ƒ8¼sïZ:5r~†ÚK(C¢&òÙ« ËâÍ0iè!S϶Qa[—ßíOɦ8B a$ð „Ô–=ÃÓE¸lCd¨Îhhöí’iÉZG(Ï– õKøE‚Poðá6ïï\Í”Ä\ zlj¹<ÂñΡ4•2o¯'SêI®t8Ú×è…g9Moa3•®½ß,T%D+2‡¨¦Ýåå¶XV†vKn^8Y=w³ˆÁÖ5@ªÓR×R.æ”X–ØÒžCÅiAoQ‹ ÂV$:¸S»†XW$†K˜'G>°®ñù+¦ÒÛ`ÀSMé´3r ‰—ËúÛçåm]k꫺®£5ƒG+‰gÍMR¼Qý­Kµ§5–øxr¤m£ñ|p® Il¥‚/ÉsüõÛ c÷ÞF6Ó„¯ÌLC£>f7‡×´ɇ„ñ<Ú cYFXX2Þ¹XC‘#Å웚fSÄò¼šlŽê©ùþ½½+<ünXJ—–Ó1÷Œ°ÇD׬N°’Šþ&¬Ê¼\1¾À”ãGíüs×iÔ^?‹ï`$ ÅetÙ꟢¦‰,d*¸ÏZëŽÚŠ5µVBf5hi^ "gåÕœ,up3M ™ÚGõeÍÏb„›ž™½fÎÛdBRŸèžj”¬ù€Ù­Î¼ûõ?(Ó­ bcJ šY”ޱއ*ÿ‡µ·G8ƒöå8#¼‚Rõ}Â~-8rS°…µÆ·Åäëû‡°ÌEââ~¸ut‹®%á”phºP·0‘Îj]ÓÞiýeɘ™Xð RŒbσälÞÏ‘€¿åòy¥ª™Œ#çtl³i"C€­×@KÍÅ”Rí^އrî¯öÛð½Ký~_Û~Mt}RAm¼(zW*@cÍẂ³ÕÎß8€Þ°:hLÆEÿÕ`m,˜(·™D©üÀ;›õ¨Ãþ¤è{%hà¿~™®«5Õ¼}õÍ’¤P%™húÉ?_èbêžùwŠÿ@÷‘ 'í´ þþÐ7v !;Eƒ‚"ó‰ œ¤œÁÜ„}N)Ï9ä(ÑücîqãËôºvßíÕkЭûªÎ Z¿ä™¬Ç,=Úa?T.ïWgeóÏF[è3—m ? ~!Øg£Ây¯(áqâ­®høƒ0LY¿15ù9Cʦx7µýb¨C¥ŸÂ¡1S%«[’qsÒèbÞÖ}©Rwr½y`²¥u«÷2ûAøz`—É#ö¤t¼c«î„õ…ÚWK61Ä'½] ·ôÔ³Ñgzçow=Ì¢ð&²”ñ|òó:Á—XÓ«K’xæRÂó d†oª=?a¦•±Ì;'ø³vûeuÌ/|¥Ç l g4L¼š}æ8+D-ÇÌt›Õ¨N,þ=¦VGõ?4¡ŠÔš<ÉQS®dM96ÍC‘ ™i^ÖpÔôÑ~AŒ§0±[W!HÑ;/ZÌÎðâÚL„*Ï~œðH¹ ð¤Ý1]o}СÔ›ù<×UIÞ©Žwh1ê`Æ¢ˆUþ‰Wf· ¬*]RkTtþë”WˆÁ²h†[*øœ R1è0›©E[íbi,œØÒµºŽþÞ|D>¼¾«Àø„A×ÝMúæŒó·86 Žø0ÕZP÷~qV…ã‰N4·za„º¼–Þv£º{`)eFï#søóªlŒãá[²÷3#´ÙÀrAyÏ:bKz˘"¤ô T³è0÷mÔ\ˆ¾À¬úíQˆ~%.Ò`…ÙÎQYG S£ +ü¾e8‰-Îë?øB†sãdÀì×þ~#‡’<5ÍtÝ*NY’pÆ!¬˜âׯBP¨òÐý!¿4Ü9jÕn ‘ ™{ ç±´ÈŽúUe¥8[œµL¬t–fá£pÆaM¦ ³…ƒ 'èÃ)Í‹©(C½E¸³®0oó~z.®óýÍ:€À«•lqÿ®ŸTgNfçI´c¹9Ï Âõ 6…¥¦n\SüØkÝß²è X*#˜rÄOñÆÅ©Žk§54Ò±”Æ·îZyH È ù>{t{Óð§ÁXQòºÄgå·úŒWæ°‡ï¾\îBj½šz^H¥£@wÓÆ»Ì`Ë~ãj«T߉h­¯»,•ºn¥ÖÌ=­h9<ì–>%e©OËíà1dرî. < Ë—°”&w(U±s ºžUŠñìfØJqÐ Œ̵ÿٌݱÂluCަ Qx‚¥_ÄY‰ì¿!Ñb®ÍÅÝ%¼™*¬Ö«áúÁQhÉïB^¾9Ùé¢ñ°5ÞÂQ®è96=‡ ·ªá‰ãèz(0vPV€ú]ðÞ"÷ÒÈ–?Êo)ûÛù%@AÏeȯɱîOzÙL¥&8Þ°Úû|±¸ˆ\èD‰ø®W}£U¹î~~õŒ(Íž?ÂÝo ÌÕóŠk=Û}¹bÉ[Z;6øÇí'­s /¾Zzë Ó¶Š\GŒ9&:®szÎ,\Ôª¦è'ïÛlqì¶9U´¬~ųU*5Ü2S@ Æ¥)žkÛ‹_kb¾ÉÁG]KI´TM m5íM¬dÒN}ÊéaBÎŽPÐJÕÄ¥†­ã…ŒŽ~ÐEë(÷Q£9$ú·ÄøÝä˺ËÙÕëPÜ­i$…nßJ GUŽ<²L >ßJZn×Ãý%·Ó,x}ài¶ÅUÏd¶?°ÎUJÜçÉWÚúco ž·Í£‚¢‡¦& ¹‚òÈcû滊"Ü ÎfÛ§Ý®• ‚ÄyÈØ&hܨDK®eûÛ[܉U(ÎÁþ¾QXW›‚Û>±¿åOˆMÆ*%NÓ>õ/eëhÒ)Æ”6µ¶@òË™çˆT-f˜Ó(BÆë†Ç4ö¯!¾íÎÖUaŠAÙÈ\=ÃÀ«>ñV£ãí8`Í©àSàdpÝ©“Yä—?«³a„̺$ÞXó_l÷?¶Å¡/ ¦¡ ®=ˆ gÑ@(¹¤'8¡ˆ•ÿ P• ÛÖbƉ«±ôm¸ª©±·Õ–¢dwè@Ól›À|úãö°?Âyï‡@ù"ñ ¬—)KÇxÞ ÕÁÄ›üJ—]ÞÿYLf ±™€¹ ž:{ádkí«ƒò›°CÝx"n6{ÊëXëÀ óÛË[È¨Ô 1¸sËôFÞ)hpÎ46’qèJBÑ=-áó·ƒK¯š©9{W+Ó#$f'•ñkó9ÜîÆüÝKN 9¤BÓîÙ4%-±µÚñ;yGCX;›Nîyãs5›í+"T‡ú–ph”>‹²< .©Ý‚ƒmý¹]Éý÷¨›ÅÏHI„øQ-±ØÖßsêA3IB«ÿK˜’@ÌA[Ìe´ødùß^k¬0ûtjIõ§¸B|“í*`¡”ÝðF9O˜dzoY¦ºìÇOu,:þ‘Ï!?|`rëïJÁ<ÛCÌYOö)âÒOKŸ~ŒÆ¹›72HŠ’*¤QEüº.Be±„3QÕºÉÀ'­i̵ –J/|´Ñ¦—¦M1­»îø™±WK!Bä|Ð$ìB¹“ù’ùë=¨³ÎÅ5;÷kçf‡n¼ÆJ=ÄoüaHÃuÊ[ËçèŸ æ ÞîL&ø#ñþ^m§FüÓTs±UDâoO~èt¥F¯éê¡~y¢·Ù•潂›×…0v 7„ÔÓ¾,¯:ݳqÚÅ÷Ìòæ‡T‹ð!üRnŠò²TOÁb Ô‰²G;¿u+º™F¹hYËØU ñâ‘q@Ì“j'äšÜvD3j<Ud-¬‹$Œ¢Åæ´J>Ëþ´#Òkñ¨êx0ÕÏg¦Š¹!®Bƒó|AcþU†7Õ,jmÈæAÈc]O¦â­]½ÑÙÞôòùkPÍ`”x¿ƒu±aŠÜP=qtŠä³HÎ’µÖQ𓸣îiõˆÖÎÍ«A ÍG¼™\)C¹f¹!ÖÕö·ÕÄ;fÎ8§i]TYõº¥–ÜOû-r EÀU?ðñµNV©ëþw§ªL÷ò¥4¸S·L‰ìÚÒïØ>£'ê%·P[‡.mB|ºO9îãDºüb šÐW(;³ÜåOÁ,ý´1yÌbáz²Uä§ß.cÁò1s@v˜4ƒ¸ë:÷ìž ùš¯J@b9Þ Òª’¶–(J[ßþ´ Eëb­Õ‘Íjw…󿸙¥DK="ƒ²I°uG–öAUZ©ÒZiæƒVþ3ÿ¡¡µ»?‘Àü0)®/õRx‹E%¥­×ÒÁØ<èUJŽ£:Ò^0WÄ1eÙ 5ض¼ÄHlņƒ¥TÙÑÓvHj×X Ï$rPÁ4ÿ3°šµ4vý°ÓùÚ¦võ÷/FW†¦ü2¬ç"Ì»#iòì#@µÎ·Z=m)êfƯõÜ®RÑÙ;u­kÁK‰f‚9Þ@%ÿÊí1Ï#}±uÀgä†$Žñ¿  B_” ÅÙHÚUêmjVv0gõH„vȶ _9ž²˜ßBg‹຺ïÄòÍßÅ0UKÇ!ö…µN\pÌNuîÅ6g^þí Ù'KÈ“3¥È-O¹ç‡óå{‘Ê‘òV²£ª¥û­«%K5}¨%_YfÍVI6Á`ùPþ ’®n2d؉]:ži„#´÷Q”ÄV"Jîžhð%h®ýT¯çqÄ·ª ¹Þ¾ š…¡dì©ØøÖ©Ào³+–H˶‚S€\×ñ˜öÓËý†^³g’^uÖ熳J)âZ3÷»ðØÆ6!.ôvÜ6»ÿÑr')—ªÚhð‘n°U¹]?§ä¦7/œa4†Až¶~®#2Iä7õÙ!Cìq긋.5¿ñx…° #TJŽÐdmHÅIáš°†sìÍx…>ené³ÒÒTÏÀb芕Œ¿#Ac•Cs«øeþ¢[*W0–ˆ›X ÂÍYѼ8ç =ÝÀÀÌ”Bcm2^yñŒîê0a"_$GÖÌ[ãôs9‡±,¢kR'GÿîzuKš~¦:µo¨rÌÈÙÒÀÑ·,<ÅÕÀFzjô¤¥Äkb„öSø»éÐ0[¿‡]p‡ÅeÑnÑý¬&y¿g¯y7À$ly¬e§¥´‚íÆÛx%®Ék*êuàÍô8‚¾8Ìœ¡Ê«Ú äï \~_²ªPo’@&²Yi'C½X¼SÑEçB¹ZmKƒâ™áä?Ñ­Ï~V”“ž‹ý*í™b7¨u LÆÌ Ã&áõÔÝ9Im Ÿ©”øXÛ *k'Âû™fVÓI$ŠÑ‰_MA>„¸Ø5‚”œ¹pí…ë,r t¬ ÞPÀÈ@WAoâÑîU¹p'j|^wûã—Ìü \èó)*€ :¹:ê%OwB°dÆäWŠ'¿<­î‡‘~¼‚Nˆu¶§å|"†!þe=(µïË9ªÉB;OÜ• ÑFäšô”_ÄVæåƒáF´i6¸Jv.-nT ʸ=EZ6Z]ÇGRĆiŽAÂ_l²cZÖŠ] ŸŒ¾NÊG#Þö")f™¯~Ýܬ‰ ¶ãšNìaóÞX†êËÿ-¥­â:ƒ·Zˆó#'KþJëRûå߀",¾óóàºdà#Ȭ+¤õ8,uÆõT|”Mç..›YJvSÚ„í0x‹¿:†’6m¦v7ú½eâ³o.k嘙9ÍÉ µlZk‘J[tz~âl#¿÷d_Vç¶ i±ïöÂy{(÷›xϤ¡”jm!â79#a¯oÙ¤9‹34RtÑqüq¹ °Vy¿©¨“£‹Vèˆn Lì†[jI5PšÜ&Р—ø4†4¹i„÷ܧ‚“–ÙÓpŸÎƒ¹í¾„üVðyÚXB‡eNi \tB’Æ*ÌÞŸzUíXŸ³&Q•_Øöµ›'è$R§Œz{qÅ|Eç±ycžÜ?ª¦Ä–7Ýåßé’Z:[bc4‹ kõÕïw>—!X¦rê¤&5ÙÜoVØ Ö’J •²hÆn$d€9©p[–òâ±v‘¹øs™~–L£‡½æüTИBÑå=‚k‚@¬ôÍ36‰?6l»¤ì[>­§Mv‰bt„Éû×5›Ë„œ@¶´URžöÚ$ÈVÙGËtZ?÷Îx& ^¢§ðž ?ñ»^J‘ÁöõÙðk„i“j~!Ð.b¡¿JÈØ_~íuG툗»ÃU‰ËùÖGªÕYTŸ} jn›,òfOþ×s1X¦†Àžæ—§áF€‡WÿËóydÙØÇi"ìöó¬>½k=Ôìlv‡»p%¬ä|ßÂUt/²Ì§ptDÚ’Å$¢m¼}Óý(»FðOôy3D·¾íæ›Íöáv’­—ðIÝ´Avÿ߉ΠJØÛœäª[/ w¯ nól!üŒ2Û®ìðÒ€BÃ:'ÁsíÒvSŽ/€ Ê-FK³ó’PVGþˆ¾ák42„–èûTÀÚ_ íú »NÖÄ=·›;@»Ií×ó¶ai¾óËYD…¾/AömòÀŠ_Ø/üY›ÁǨV(`k¢~ôƒ@—”÷™î¤ ¼¨‰>ìúÚ ¸€†SY“#k÷Z*KþÊø‚î ȇQ@ôIXa¨ ûPGwëTui38³*ŠÂdzÁEmÐ2Á3mõ <$îý *ÈhwF‡¬‰´ßT%ØÀA#—­+‹qù¨L%Aá;çøãëmÛÄe;…fû>\ØA×ó”“éàîs³R™R|kkç4þqòaîCKòq„M¢Í‹sU¿öÆ„“èd&åÍù$U½}IøziaŽel3…XÑ AXóVÀ`í/ f¬Sn?…ªB~<ŸmÅr¸mß.€“ \¥átÜG|¥œn.è²¥Œw!„ÞÿéÆ:'[ZbÅ&AVsô1RÆ’‰ÕÇ Yg4\Ä > ¿CÝ€F4ÈS1ó\},—ÀÁͪ%ÍÍÌ%­ &B¸ŒÑ–ž»ŸÓ<}œ¥ÏAë»wºìÌD”½#ô>$gÉð‚ÅÊ_æÿ´BbÇ…ÚÑ–8_žY; ŠûI†¿2)€$ÞyYFç°‚M¶Uý1§ý¥ ºP (ø¿KNû|#Eæ„ç‚'PTŸÞò )§bZqÅ54 +a8²HMª&4 uŒà*ý´#þ"¹ÓÁPŽÂO†‰§ð†nWìðŒ‰Ð¼ë ëg‘ã_µ½j@“—Oö²´-«Ép+=°Œ’Óé2zy“Ýa VØáO”aj“G«‚Ì N\'€üãt\Ì¥`|0ÈüžBÕš(ºèÌũբ–36öíò²ý”izSQhÇŽÔze—-ô,Œ”oêè”géÒ@î¿ÂÈF¢ÙÝò‚`z}ÚùÉQ2¿«ÁD;´Aÿ¿ÑýÔÖ‰9smNßu‹Ç–Û\ k8[ç\¤ê<^[êwswÏÌ0€|š ï,ëõÑ ™ð™Ë¿JÇþ‰,õvÚõx¬’Èá2&Í/U<à WÅzN mŠ'ä¥[kÉkWÄ«EUlÝi+ÇÉw›ÓÇíe 2YékbÒUFm›Ioj)059býTÖüzºðRiœ˜ )DT3)ZØdQ÷Žç@ÈõÞ¡ùm³ãÁmü$‘•X…»\$9‹V šM‚ÐÇš­b&]ú/÷ArNòæ:'È.^d¡É»gÉaJAî- }+»‘+Ä–ÊÞ µLà³Ý–\qì3´åDê\`–4|16GYc’r>\ñA`Ú OKó+8Kï—:jkؤ¬ÿbÅ»/ë–}ˆ”J‚öq|q)“»P3ïn¶Î»kr›Ä_ýìp/1‘zJÄÅi©×Œ^á¨Zo8­“IJÇ]®FB>JMW}b†ØŒ¹ûŽŒ“j"u ùª‡bZð \¥L¼7³S-þdy51ö0ïv äÓÍ釗 Ô‰µ²Ý”H¾féÇY­|–^kZû5ÂðmòÀo Ñã¡1Q…×Ö¼3dêâÜŽ{ËZ>Ì⃹&¾Ë¯•x̦¶¸7Þ#^cä«WE âp¤]•…á?LpÙ$rµaô¾åáIÜn†kKå9ËÖ¿õi:£ØSÍÙ"®ŽZûzéÓ}á·+£V“¶‘’NZ.!žëgÚŸ‚‹‹-(2µ“¿Öz׿M‰?ãUÓ…ñFgÅÀi‡ÕfTÔ¼ïQNÀ"ç­(´lïë#ïþ°ßí£õ¥… ƒxã‡èPÑÒÑ:Ìi-j2›Âc›¹æî ji¿ï….® ½¬±ªÎV4eì䟰©?tòš¾g½˜à{U^gîa V(#® ž¥ÎD?²ðçUÏË7@IŽ‚Þc_s&,¨°@ wV §K¨\ÒÐ31«O¢þØaý‡¾ÅðŒ†f{i8Å‘%9>k¹ùê„ ¤µ´I‘žÛ<.¤6Ö†•ŠkS MQ ÇéšÆ™%¼R4>˜óþÊ ‰/rN•9çp6 ¢CÑÌ}¤YÇÚA ÷Ð$`xÖ•oÖÝ×Fò½ºϽÇYüмXÕAcYžz™Ö‚Uµðlåß3ƒñ[–/µ‘1GIÜ–:XÌ*FÖïP–rUE™pÝ|/σ4%˜1åæÁ,(62ùÏñóhv>RdÍ×óVNZ‰ó¾±ÏŸPLû3™Ï;4 g6÷$(,P(<ÝÑÆNÝ?Ú ³x`àû"ŸèL‘☣:MœV4)PSÖïðêçÁˆi~¹Cw@ôy&¼i ¯g<ãceî?dpZ É gÔŠ•äÎJ¢ŒЇ"ûõÆD¢ÿI7ì: +õ$VòW-žR‘b*ËnO¼q‰(KˇM“ƒ ¼’¢,1.à+RÔqj7— £Al0îä¦ð¢+=»Â-GÓ­x]ÛÕ!†hWÌ›¶ã×<©«Ðà4ö‰“Yì$`|ºiº «œø–È£‚ÚÄ ¬§Î6/uÅÍÁ‡™xvÉj‡rh2dÂ×Ûféx<â“pþˆ î† Ð:ß¹K¨dŠÎ¶dÞméN{¶üïeÖ CÑ FNtüÄõË.&Ýðn\¶pí`E@åv%ýÁžÇÜçs7!7ØÎ íù¸„à0ŒãoðV{gª7»\êskïã‘ÖŠ€ëv$8› · ø‡¡[â5ñãMÆ3ž–¼ã³^^'‘<;Æ9""£8ïåÜœˆï®3ð~ív‹¹;lñ?6YHà@èfÎû|Rb´Ýz!“Äc¾&JôAíŒÆ™_×o‡ÚPE“²2»-’YÛÕzÕo¶Ó¦{2*FÃê¯K[s\nH‡ù÷¢>áê21;’±ŸN÷ü°Y"Å‘Íõ½dÜ´í _^&Û`Úï÷nO%Äð|šþ·ûÊé€÷ÖC¿gˆñL̯ÑÍþHtY©(zÉ|¦³¦™Wþ¸Ü)¬'¯”ÝžK:ž/¸]õ TrµrÓyôr†j“¬Ã rì‚«øXí+¢°½3Ÿ¦ÃzQ±ØoÇ únΗ3çžÐm"/JH=Dh·„poõ©³~T¦Ïm…5|Ì)1qu«qÊqâxVrõÍ™*k;Þ">ÆÈ¾!“³%CÖh ö=Ö¡Yf~ð·«4€XÝ©¤N=Ü\…ôTÊÄåÞÖ­ççGG‚ƒE*àê› †Lî%$]óàÐ$ #”§²î'áñ9i¤3ª[zZê¿Iõ¢‡Ë§‡¥Ü/.~;•¦ZÓö‹#zZ•@‡v§G§Usæ0³z wpÚ…,$%PÅ/™’“H†¢ÝHW=§ƒ!wò$«¿,KW+Ò'ˆ¦+{±&‰æŠ°rhh * ËÝ /à©#Ô×Ênï5u`@eáªô®¤íæDí|žh~½Óº+åëõÓšÅЫ ˆ“ò1|½^uú¼rö÷Ä*fTw‘*°ÓÔR¤‰IÕŸ q”–«ê0)Ïšç–úÏ­CòôcÍE%½”çÑá¯Þ0Z¾Á {-G¸ø8e ]qUÔ­CÑ`C”&ʰ"ÿ¡¥ž‰¾ü0}êL“ã¬ËN/€/5 ¦>-z¸#‡­$¯§A=ÌuE_6NªªNÃW*‰Å™oX’k‰˜FXk‘mχ4øC 4¾•ÉÙ+s#‘å|=ì¤'X m°u kì†lÂ\¾š§2FC ”£yÒFו(EØÊŽ~5>û!Þ­*‘d8¨ÊüDðÎñHÒ`òËCããÆå0ìåvA 4ç í_ã&Eho¨OÔ>\ ôî¼²Š–¦ £ÅGEM¼î¤i³ø H±…¾Ø ƒ#lì1᤭¿ªÛ0îës¹Î’¾:|寡˜´XfŒ‚ÛdÚ Í[×c˜Ë4kí¹<øhÌInR½ý½ûN)åL°v•0c¦G©€…XA*¸X~7õçÔ)¤(̆œš­80§UûÆÌÛnûjö÷ùРŶÍfW²9蕺Ö~-¹³Ð|›±œž(nv ³‡âᇤk™R]\‘íËОoiÈs”õS‡EœªsÉÑo!¥©EZ|'mVÉôÉõœc® Ö¶Ò¸„ø—t€Œ2/yÅéXˆ† —Ž¿­”J8»P¶JyÍ.š“svAÛšCp’::›9ß¶ƒÃ|47ËÍ)ͼ³º…X{hJBºã•GE^7?ëÉNŠŒ™RìðôÌu¤EVJ:Ü¥eçShš` >šß@ÌËŒær|ÄLSm:¢íºþReï÷½Z~—û¾h’µ,•ÍsÍ¢ÎP(±©å|Ç ¼+| ’öÚç/`‡ñ÷-Ëw¸4À#Œq`ÖÔ¤·€AyHü¿ &µØ8Ï„v£Iqr |;„B3÷•ΚƒúÙ e]˜†Î µ_x.â ©ªšX`ønVżëÎë®(9_QåVT•²þšwÑn}Ü~‡,‹V»Xê±vé½ùŽƒÅB4˜G§ð –"ˆÔ$ȸְ¿ýhE´i“51Ýi}È ˆ“³Ï û—ÔÉ£¹éº¯kÙܦ;Ê>‹XÌEÙÖ½S#—n«²¯ùoð„æÒ¬S[,Ó)ÝÎÅ7a˜ÿ§Œ$£k)c«”c;tMSm꫉·j¬%›„Î9¡F—¯wü]"a©O™g/ÕH}×®½8‹RM‹b»í™hzÓºü†üúY!™~þPpýM*¾ü9Mm¿Ãû0M²»c¶¶?_¬ñ½ñ–4Db¿×˜2—JSkÇš%„zxú³i|ÙpBJaJj¦“}¡š–´›:g¨°yÆ­b¼³Í Ù’:ÂOS-Á£b(У\ß0Ù1‹ylµNÓ1üÃ=gH‡ã*êýoñâ+þÝQÀÙ`eÅÄÛYeÛ¥ð <´ùÍÎUT/φFºó[Ÿp8rGV°yÔD/QHo ö#QaÀ°· ź:¿%H^rMu‹]¦ýþ0f?ÿ¸dvéfM\5…‹"’LFžª¤Äd+‰ ³—sÇÆ(Šç8vG”7mV8X'?sR±GŒJR“zZH­× Ë­kÚ›ÐqEé1ÍÃ:w½ƒ¶´9Hõh™]Cç~÷èÓS@ñÎýßP{ªðžE?§Ó€C•I/4ÊQþðîij®Û-w©¹°ž„î~Î-”ç!B¸ë}>%¡cCÙM‰äÛ=ÝÀV‹óüt²bi$ØMtƒAím#qˆWŒéÓ±FGöŠÆ¨zÃÞW?®y7U\ÜÝp^p£é_é5z-®þK¬gaô[Ý©íãb°L ºï¨)`Ê™¯“[ë§æ/¸I²CÞÿØ’{w^Wã Tb!P>Õx•—è.-¾þŸÅ= o ]sqBã+öy‹uF#ÿÒ2¥B~3ú­ÎZL„14^#ßxtbõfÓûGAAjÈ@!‚²ìØ“†ô¯D¹Ócà„˜¹SèM ¦e'äUÅ^‡Ÿ:lx¡÷½¾Ù†1Z·æþQ‡l’t`£Ö¥8æ·R:Ñt•À¬¾ («Ï[õÈ*+ñû’Bßñ1˜F&“ÃD·Ã²!ÔìS³æÓ$*ñì+˹õàØ3.ð¹t1}O±Y•$YxÔ"¸?J‡Æ¨ ¿±hq¿ÿ®;Ns„lf‰é=ÄïX^‡@•œW¼¹ús új®Åyc»~wUXjv¬¼ÁâxÒGO^—GÊ aþYªÛÑã mÄö²I€Vuú›L …óôqü¯ácédÃKœnN+Ñݬð#Lqò.ÊÁóRKºµÉ—ß’{£¢P1“ K_`ÃPD`ùYÑP"±óö$"$WH†@0ãÁ·èø{Œƒ½âe÷…¥ë;¾¾Är~F£Ð¬M äà~B¥2Y«&ñBÑOïH`EÎ)ë¬Á ˜øò&t@YaVŽˆÅ¸æJÖ‰F>öXÒð+$U¢À¹¯Šˆ;ÈÏHžNJŒ"H`hìGñä¢1MeS32¹cƒg™Á¹´À!¦ÑÙÍÓWÎü´“æ6ÚÝ*Sv˜]##T5Ô£Y"2ž¿|!z µˆÖ G‚‡õ.n\‹ÃA£fByŸ#mk2d«%çp¦ÚT.À-¿Ú×q,’齞 *4øpúTŒ½K•¶ Ž+öjrMfBž¸lÃdÒ¢ey`nÕ¶ã®BZ¥ä!GE ‚%„øÆFϱ>k*Äâ%o]IjWr«@¯jyÃK¦5ç8j4ÂYçp‚}9¦èºt´Ãªôl%aF¥÷¡ ÚqYÃ`z ,©c’ÌPžCχg9ÂOºqDå½DšeÀo„ì+sÀI~{ä 1Ö\…ìþ‚úÐãƒÓÈR±tÿ‘(—ét_dr-¥~¹A™ù•c$"عê=4‚AâU}ß1joDð¯4lò:Ë4«þ5θÔõI{k±§ûNù‰â&L– %³Í: „"éûƒvGÓQ~]I)’Y€ã"’/‹Þ+ D3k |5—ý?è±ÛîT¡û¶‹MCPÒÕ-³L€þáæª¸ðA»OŽè,œx¡°c:. ˜VŽ>Ñ‚á;vå#ÙyÛˆ»¤™ptÇÔ4¨Çm|ÛjÅç:ùp~¦G6±óâò8Z>ÂÓ•ŒyH¢“ÄÔ<­8.ŠÉp}>z¤WQ{}ÿhCLý"ø4_Ã׈Ç*q¯Š"‡„Pn„7qýuTæyT9öÍ£¿ÝºùkË;žŒâŠN¤šÕgÔä„}w Üƒ-Ò€µ¿å_¶uw¡±C1OrÜ傞ѯ0á´OdzΖºª«CöŠ2 ö̰HŠq¸#/ŠúøŒÍD+¢‚:×§G÷ŠHj C’FnÙ£Û¤ÃXÚƒfRªRNÕÆò‰¨ C*}¬³•Qëñí`g}ºiü¡rss)¦.¢ËG¬Ú`+KYQÏÿ‚+»KÅÿ‰ÃÖfe£R:ÔÖ†¦Y¯˜÷¦ƃ+ÜÎï…<ÙGBTǤ‘bXi¸®Ìü2A*|OKܧ=IÉ%ä&Iê”~â@d5#¸Ãæšœ;GÀ¾Ïšg§ºŸV}>#à ðìk‚ç”PcøbÇMî€Ùò‰x=ÖÐ}Ñ=°!É@-„pôI¸`g˜Øú÷£R ´$,øŸö ôÖZ8¥jç§ó4Iu¼J9ëíŠN°¯,Þùɯâϲ·f*.ºgâô±ªaQˆQJzñ„âá -+:'ÉJèÕÛ2…¸)Ä p%zU¡wù¦ÁÀÉ©·ººº®…)eÊ[ JHäêþéXäoÎ×ï¤4<2âÞ›Mãd÷§®Yÿå-;Ûw”¼ ÂaBr§ðÞB_çUQv›Ë¾C>£=ecÿ²~ÿXŸSERâ=õdáµBkþãˆgWP 8’jüJœw“»?vž‡ž¶)aö^vLÖÎz¿1DaZ›ÙNiîÛ21 f_ID—“ÈIJ1ϬvtÜ$ðÀÞ'‡§Ôázªë°üoûëß\wP›0¤`àHR ‘nô Ybw¤ôb>:FªGýÖ|Bd¿ÿô B3¤Ñ²ã7KEŽ.boÐ"ü;Ï?ã{ºQU‚ loÌÜ5Ù<äe A•3ñŽî+€‰98gº‹&’­ >ÎZ!ÃA¶Õ@Z°2ë6o_‘¿©äÉ’³†äMÈÏÿæ >tgD‡ƒÛ¯‚ÆËcì_Ô¡>šùÕXQŽJŸEÛa¬ T_3Á… fõy‰µ\åŸîqN2ué_ƒÉÓiêÞÕVÞ4›jš³4RzbÈO9_=”_E;¤ñæ7\à,ª§“”€GJº*SÊvÿQvt¼àüÒi91Wf™j•½¦“°:ù™ék‚¹h­ ¼ú)m,^IåbSéSõ¡¤èGÎŦöd,ÆKƒ•ʇ’õ´èí”^ì–I Û‡±øÕAùL¿³n"|ìJÊî¡?Çiä•3É;!‹{ÏkÝ¥HKÅ^vw’âÔÃuo+y‹ª›Âõ¶“P˜Æ¦Øæ\]ô/ÎŒ>Ë"&b ëÇÉQÍK=|œÆïx¸˜^F G7Ù,áŒ[ýñ´ÛÂõ¤F È z÷Y;Ð,ZAìÉ·‡ˆ_g:„©ž¶\Žþ]l‚E±¶¯É™)ã ­¶Boc8:s?ÍÂf)ÏZâk!ó7¨0_²&øÇu’D:÷–{"uwXÀÏ]é‚Cùõt}ÒRÝ3ZÇqçXGSˆrzË–¹>]Þ赆oª×Ÿ[ ™J„bfhQ(‘n·Cz^gÛ`¦v%Fé‹&{Ö°ÝŸzdÌíô§OW`:øÃVAIÊN˜$ÿu×9HwÖ͵&^5íçÕùǵԂz†r·ë™ír¸2Ⱥm+n†`ùEzŸó+†Ð>“Û2Y¥é€é*òþ-k޼jçÖ“mIKÑkÇÞÍÝøeùpõ]¿¯ QõfUÜFãÏ9Ý‚šêFp|¨·pcrÄy7[º| ZOé7mnÑñ²ì©´s éDÕkFêg–dD)„òî­œ³X/€«.eíÊ´RW¢ìq¾áy²Â¸ñá>«å7 ¦ZçQŠð»KÚW3.Iše'‰—ÒŠ‰ésaû¦5Ý0œ¢”!1à÷_zÇúLsê«ÜVÓ)¥ÒéjéN¤ºë:_U™`öåñ :Kþµ1¡7ïé즣cr¶±Uçç¨Øžå”·ÍÝ;xyœtú‡ûƒ*FYÚ¼…â¾ñ8±ñY^߯õ–9ø4ý a(Ê‚»² ïB‘w®D4ß›› _1Ãði[þ³4džfßhÃÞYŽ w槦½HóÛ¬ÞˆÏ"ãþ‘„îÝjKT`üŽm3©üdɪ(&ékoƒ¦z+‘ Ž T ‹U±Z:P,«:OÁ‹"uÔ™Ôit°bÔ¹œ¿èŽ~'Aòa06H§€&…ÐÄäF`Ëôáκ»·¬)ˆç_µoË3 H/^„¤M;¼‰?*þHéìÏuê¬>åú}®§ ü회þQÕpÕ¶_ÇycVc È×%B·Öïþ3­PA'f¶I“b<¬6„@1ãAˆòU …5ÑIm²ï¬äëšñWYUm¶z¦ñ@dð7a‚ü¥ÚäB” F.ÛºVºb æ.ª[ìÿÁ :Œé•cA<‡Â‰¸‹Å‚c;…­®Î-¾õ7ÆÉ® ,Š5ŠŒaY‡« `ÍC…\‚¹þøþ]÷h¼¿â+E:¹ê£¬‘yð€.«“—}€RòåîccÊÜ&B®è×ì„•PF7DbvŠôtl‘0ŒÎV‡¬£¿|k3ò§ û`×ͪH?TdP @}½á“îmv[ÂIš±UGZ°8¬‡Œ{Þv’q•,$Z¹7RW?¨*DÝCÕÒÖý€”åOçK‡ýìV’=§’Èdëj‚ÝÝPÿù1(àÕ>æa2=ãÇÿÑ:=oë(§ú‘R2>ä;©‡t£þƒæn‡¶Ü܈â"dÒÛë)È3ôG-+jÚöZÜW.Z Ï©øx¢É[°á3Ô&'NG›üш+ŠÑÉoÏÿ G•x*>É©ÛÚ°±~ !Q¯ÑˤºiûÆNî$‰/=%ØNn³e!¹²Ü)VÌÎ=Jœ¼Ð]ÆBj9nÐåmsU°ÄZm4ÁÛÉ~VØsPk½¤§Rªç«óÈ_(Ç&çÖýåpø5}`Ÿ7¶ð6aD÷-¥V#Ôa™´‰†^¼Â÷ G™Z›²¤U‹ž˜;k@*ŒžÑB¨FÆŒG4ìhšÌíþaH chTbEÊÀŠ´¿5[€Õ*-) ê—4|¥¡pU^uƒÍœ—ˆ¤Ùäèýa<9œ!ÂnBa‚@¾P¥%åG5k“Ç{ ÞìË…Ùá5ת.+fXÓü=ÃÃ(ìÙÛ¥èj¸´)vñ-…º§OÝ]³Ã«'¢Ã4# Þ•cw3¸ØîP¾áçoÆÎ£â7²2—…ÔK[{ó‰-«frÒ.PdªødUÛÀÛG••¢rÄ,Oñ?•÷'Cë÷h×Y õFÚµ÷ölž\&š»’ÙXÂÐ!Áܯ6Ç‘4"?¡š6?˜Wu·û阫¹‡·ÕÔƒIw2â2Ú/ßȸ¯¶Õmwv˜hÍ@Jå×íî{<è1~KE v¤¸hCí³­û~rÐÜR ŠŒ0PDhLYº‡ú°RîV6—MÌøgí¸qˆ8kÝfe¬ º¶piùÛ3Eµñ$6f}ÈyJê£ñ­¯$tQÏÇÈVó&Y%ÒÐXËtjõtÅ]ž¶\5‡‹m.{²sšP­s-Æ5¿ìäI¶{Þ! vµ!ydzø(|¦ï|ï8Í3>éùß (NJtáU0øß·xB6EK;Í®`Tï½§½wGKª2-®sÊ¡•¯~Y7(Ñ à·bï¼o¢žJ4•ò²x¿J¾-Q…ÃBúÜÌ’¯U·Ash^"vPtF‰ècÆÄà ÆIý–*4ÌôF¬iBY–@é!ÒVÛJ>Oj+±y+—eìIBü±* Ð\#l”çâ¡·cuúU­FÈâG"ý¸N¢‹ÍòËaPÍ[%™íß¾+Øü2Û=æiγ(å4ô Yî]é‚?ÊÂZž0¶™±fÁ?ÈwNQzÖ €Á°»¢|mËç57Î`ˆ„÷QˆÍd×7%Ü{Í“°8ÃÚc †…^¥«„•n¸9¥b™ç^ilG¸¿Š¶ ž‘Iºæ q*ƒ‘Â*Ž­œX'UƒE–nCYÞ¨vÞb@)G ; B¿GÖˆ9 òq§ö%Zç†7ÎÁ© ½«’Ïð¯SE<¸l?y”›Š@´B»+ ÝKŸ0OaVË/Éì½Å#ÄÄ×’Zg `#Ë-íXtó'H—µ ß{ ,¹ÑãÙÅõÌ܇Ñaíê²]Ì€ëWB$+íû>¼ƒb¼çøgîãÛó,F‘Ƙ¾ÐTMy6áòÄÊþvP-ŽË ‹¶é—1òü®•KÚy#(øFhüxÊYøkÂõqW·ìg÷Š‘‘£—¸¶ah¸Ðd´žù`vÏ-ÑCH¥åö‘Ÿ<:óéÑ™ŠºM0&^<‹¦­ŒÛ!(;ÿÖÄæ *bö›Ô91à*{„,Z-`)]- A4ca­¡S„BÛ‰§ÿ¤—Bþ·Oò ³ aý…:‘Å›^!ùý|&žïÄf0œMS}ª“Kr¬µŠç%QkcáüsW E¾‰7”k$q4ŽqòO*gǬ¬ àØªa}¿Fp~±¸bÚd±µj9Ò3 ÉÞÒ OP¶e×vSLRÒ%ôÏ*JÊ®Õ-t5DùÆï‰§#Ðò"Ѿ»9W¯<ª©´Aì›fÀ“”‡!œ P×”Œø~Rãã±Í}·Šô!ÜŒ Ã׎×a!• ¥@çpÚ/ä,­rz~y†Nßs˜eÍô`תéx–Œ‚Ù—"!Êèœq—ÑŽ”&º†`(Ó¾áô¨æÆ«ô¸\þƒwÚrÇ«h#¶Ñ†{Îöc0ô“•­J@†u~"©pÞø¿Ft9X³jCÖ[/™DóÃÎÛ¤sˆm¶Ú|ó²DÈC´}¸¼‚˜EÖE4ü>{ÞQ¯GÔÚ)õ·×9Ãc·"a’Î3füG7 t[n@²ˆðük|7Î2H‡3Þˆ © O‹rÌ*Qìôt÷míØpMëû}ÆeÆšnbú£œ™äpF·|+Ú(X–×O–"¿"+KÈh~ʾŽwOÇ'.îãÒ|ߨXÁ(¬¡ßÕAPà³á9úf-ŒÒR ¸­§ô`) 4V‹N ƒÖ>\É9Ú­nÛ:[ÏL8Xð  µ§§Ù3"žÊ"o'U4F‘Ëv{_aWX.j6!%hîp¡Ê€0S‘´îí¯FD›mÄâ½…¶vY¯]°ðÅdõµ6µ+þ%eÜF-ŠóñÆ Àlê o d,øH%éXÐ?Hجt`ìç:Sž ) Å1÷ èz(êÖº±èLPÊÏ2‹ÆI¼<­ÇÁŸª”• ÑçO6˜·*a´¿ü†ÃiÂÀ‡òO%Å)XH!\ÇïçÖ½˜¹pÒxš\Ú!>ŒIÃZÀ¯¬@Σª:êÎóY«$¢¹d¿·^]RK-AS˼šIaúyky0aïpg2íNL*¸–vˆÚõÔc¯œU‚ÜwJ}ŒÞÌVä³bÁü>ˆ'wMq”S»ÕEÆÊv¬¬¨e§­ßØVÔ»20e”éFD§˜«VÚ9In¾ûÌ)QvÕf'7[ßË Çè6ê#‹´àÎÿõàmJ¢héAç.o\Ÿ÷Ï9€ÈJiŽm²Í}%ûѱ³ [–‹¥3Õ_–â94ë•Ý.“&†^u‹ ‡Åò´[³ÉˆÝÎé{ uãŪ¦+¤³ëV3Ómì%›4£VYŸÍÄ)ŒN1Èì²bšð“ÊÍÔÌЖf(¦_¶üµš0 ÅzÉ®fS’ç&à \ýïy¥Óέ½,èêm¥(:H‚çï™Øª²V3Y©F°+ÞGàCM:6\Â÷ÓÝØŠý¦ø…PÃ?s|0 dÔâdeVÆ<îCü@Öy aºÆŸÛ,¤E¬˜§J2É..Âhæ4“‡©×]çÞý†¾m’{ÖØ£Ø¯¤9sV”£¯ÀJA£¹^ >ýžµzD”êEéM‡z;ä™}É[ËÉž#¡ÜAPr¹@fëw%¨þ^s¤œœž–‰Ü&!»ðö˜k†NÅLÌ$΃Լ¼ú(ï*¸÷±BÂ׎IΣ˜Ôµk‘o`N¾ÐïnpM`Ê $M¥¢å Û1‘2¥¦^ìNâ[ ¦8GG&‡NÔ Á ÀÌψ¾˜vÒu€ù–ƒáÉÈqÕy”é~ÁÚÞ‰-ç³øÌiùwDÏ%’ ÐÒxJ¶eénD– O ebf60‡_‘„cü¡È›7%#Ǽ”ˆe@Ú•ÞàbV«ÇN3N,³¾+_þ%òìÏÎAúr8Bü“KB …œŠÍeÉaÜ„ñ:Ìüܾ3ÑcÀ8HA6á͹Õòr>3m«{ܽrKqE*ê¹Ì²J>§t4& |n˜n¦¯ÓéJd—-”E³)Ýîõ$>Q±UÂIáyM¼žó@F°á9ûG¶z,ðxJùžø´Ž–½ÃFÖ]™¢?KþœAд_Çdo Lä.릓ˆK2¶.(:މå¨ÀŒ9 “wxpËiúÜ­Y»7XÍjžz4ï¢èMΖ°EØ/ú1º `FEåvk-Ç'su¦:M§œ/ñ÷Ópþ­æä'°?%؇±Ö}Ç ©fÓKK楒ô™'.àý€ 3rΆ¦N¬ŽC‚×dÛWìÖZ"åá ·n„¤_„¥´®ô Ó“—Ó0Óq>•ãCAã÷5uG­Ùõ‡½•휀UÙû´(Aþ)wÏüÀ‹ä y­†ñÀê›±“ì—šh?ˆ›/Æ(k!âÉØëç¬Ùé´´Ùªxr ¾§ÊMÙ¨‘ñžú£RJ@J¢G®Š>ñZfZ D\´À(øV/ä@׳X¹=e ñ¸\Wy¯4uýoeH\SËRËŶè=VO®þµ¹Xø[rÒÓ¬Øùg3p¡± ïQ8 ^ì2uæ NAƒw !Xå°Ö…I¡Å0iß4u «æýþD¨”\Crì‘nkU0¿õ"JÀã4i"\½UbgÎÏ~Ôi:,ÛËqd(ñÌ9W•ë‹ Ý(¤0¸YGWGÑ"ä8SêÛðá©[²ï¾}’êã™ü½²Æï·VzÊ`b¼“´h§ágXÞ$ŽûCǽqO¢$=é €GµGß¶>!’~¡u{5ÔéÚñÒò ¶â[Sú—3“©Dht€«{êd…¹ò&"’ÛÇkLÖÇq¢ý³TÒÍ'(×msѯXH˜äëE”f=Ǽ„—õrê O5Ž~óŽÂñ¨×ŽæQ9( Zd†t¡% ëO5%¨v…S¹»% Ñ¢½8FÍ “`êÿ‘þùìï0øqyÒ ÆhÑ:72è½»àÏ´–øZÁã»ç hÄ# ü‰§bìqÓ‡´Z)xaZš£‘Ö ÷„°¼wévŠŽŠÃ¥³ý¯}Ë·‘+F·Ic“°,ïIWjJGg¿à)§ãÉ)dMb85í4^¹à2Q¹ìæ Ú«dOË96ÛŒ¬EjòÞRLf¦€EƒµWÛ—‰^«×Nh..s)´ÝÄeš£ž¡ãeÝWhÄi…¹Ãe‡Å4¶—pœdjÃð ÍÁ»ÈªIÆ—,ìcèçj¾¦à“›ÍÐ:ÀÃJwÓÃu\®Ô^"X–>EB…F‹ÝÜÂý½‹iµÿ¬ÏÛròï#c[Ô¼ý)ÕP²q½ŒlàÙOº±QZLÎçÁóßÿñxV©6:@Ðæò«UBÎ?”ÂZ™VBT€¼ËÐ%é½C­]·t êSÕd.zO”¡ÄžÇt@QÇ—VºwRzí˜Ïq©wë†/z™3н¿ÈvIyË Ø‹üäžg½oScü–¹ŸÕ"_—Þ(GQ)Ç»ìE›R~ù¤®þ ÍPß„c8ÛªÔ{yú‰Ôlå+}YÉ^“ã‹H(Ѽ(ö~¹µpLF¾h¿Ì]‚'Åe4|„­˜»’_­»§/ÀðŒZD&-.Aàüÿ ²CJd¦s ºTOÙãÜ“–eõBo(L‹&d¾·=5O°ïŒÊéÊ,—°Ç·oøà…)xJí”G5z?ö_5¾îõø$§õê™Ð-VêÉçòC ¬0o»Ñæ¥{°q…òôÃe_¿Wñ*”OÄkA×ÄØrÎ]Ìl`ꙉŹÅ8KKŽ—óaiÊð®Ûz´7º6®œe˜²+ê¼ï”4Ãy àÕ({îRÅ”\ŸßPʼ\¹·O”ƒ¡ÀS޶6DPÑQ󩿍oÔ}$!Xßî†-[g!D\äÐô™¦OF•™þv‘Ð4®¬¥L¢(7@„ƒÙ˜IA,¾áF™üiÆâÍ$¼¨“ÈDùS§Å닊ôè}®79ªÇFçéVÇÎ#bwFž‚¶I5é__FÔSè«Ð–ì¶í™?ÜÁ}åÚ?­+ÿÈœ_³ƒ&„ãÒõè“!<¿4xÉb =èF;ïè²Cª£'×ÙÌíÊU±‚s'! 2²1й£»mcX”}é€E‰‹žËÜRï~ÇÏý3ž8S\ª§Žmê_*cžãĽË,}L-Hkf] ˆÑçVz8öèÀN-Í@&Ÿ3Gç‘ï@}ÁlU;«´ ëy ÉØéê’Óu˜ý¦ߎg•>ÆÚ{Õ¸2ö—{OTôs؃Œ§ô’q¤u +³öî½4ƒvÄÚøizZXI0‹®™y=ŠD,ê¨fR( è°ymÞZ³OYhI0ý úÌáSMÕxX«¿GaËɆÙÖö.ñÔÒšw§˜jÓ=EL®¹y}ã`þ×=Žú‹faUU/&ò·ðýÜ„™Ãçj·nNpu[ m>á¨ÔñBe=TJ|§š˜ù,a7ˆhïCÄ ß©y3àƒ>Zð‰“[“Ù5À/;;st½¤"1ÀRÒ­ Ž+|üûQ-‰ÉûLDÄ©í=†Ç×€b‚}×X¬'_ôÃe iе3Òpí¼D£÷@m¿Šrßò‹k¼p’ƒ87M[Â4ÑŠÒÓù¸URzÂÑ%¶ÿoÉ‚ø;œKê˜øìÉP64 ÝlVãBÑÁ#ÕQÒ»12 Y+ùé;_®í” ¤šm ¾šA*d§)'’%X¨%…F'd>WÎ<µßÍ:ôèõ¬V¦3øq±ÁçÎ:ëh¼g1mz ¿Í×ðá‚”ÝEÜü |µ¯ϳMn-gþ-ˆhOva“÷“ïnpÏ>â]÷W¢ÖÇyØSÃtÖSÆßù –9·7[ÃÎï§eæ>á Í„N ^qýÀá‰ýÐ9<1­Ø MP€¬§¡¬’ÜŠr C$->Û‰Ó¹£rŸ˜oÔ@­ˆ®ò].µËp»aþÄz¡‚{Ö RrT6þ"±ŸØøŠ¢ßóC10YËG5=ÙËÕeo[ò®—ïMðžÈǹb8ǹ|qÁáš¶ë!ú!iF^Íå™wž¢«I^,búj4q¸ Ä@2†Uu›fÁ(Ìî†}³4©_RV‘34Ý}‡ n£’¦ÔÔ=ƒÀ [û·ðdRú® W<Ú¸Hõ;÷ðÐ j€/ï¶Í y•ßjIïÄîìê…ožbl¯ ôCƒÇ_CòrÚä>Ýi´€PÔÐ ~ý(µM,‡#›Ãgªx§ÃäNîË —úŠÕ Ì䇎©ÞKON¦<½Cvè²x¸›Ô–%’J˜ mޝ¥³¸‹¸×ßt g{Æ&kÊ]ûTg˜×ÃÐñÙvU¼£ »¸[­£üW /Žæu x†t§Fm³¡²¶§nêÎÍ…ãž(´€6UoëÚcˆ8ÞûZ³X±Ò”©Žü±½%Ì™¹Æì3xͦyÌžÕèR#yI±«d±¢^7+còÂå­©âÙä‹¿9ÍÙéH…é‰×Eص-²Û —PcFf\ Xï®Ü6m":bµYP2AÛRtÂÇñ±‹Ö¼wÎÒJÛlòyt%‘uuŒ´Eú Ù÷"Ký/~GµÝ±bVƒ“ù°% ìq®Cc~@s ,ôTw¼Å@þÿd'ëkïå8ÞŒÊò˜ÛÕE‡£÷‡©èCqyͶãÜKO¥8è{gkl²Òì^…E¨¨Q{HVÛx‘˜\DýûÔ sÆS²8 e7î¤0tÖWñ˜y¢äÖþRÖöî|úg-’Û¦–Ì#YJù3·ëádYƒC“Z|¬ÜNMÀ§m ´7{PgÖ–Â9~{qÃ~Ï]öœgq)'Z­œq3É£ýøåÁ;óþ.ÿX̹Êpö[hƒÐÇ´d‚ôaY›_µ0ê_.j•ÒR¥Ð¦ýԦܑiâo| s½îVTñÄGÊ¢j9‡ò+U PEôp{åØÑ+gÉ8Iº³¯@7Õ÷( ެ¥¾‹YÄ×·wÀœôŽ0âûô'¨³_f)5¤Û4s D*Uf&"mD•diDÝ~ á6 1\Z… =@Á®€ «8~θA:Žs]ý¬ú±D ¿+puã™Uœ¯¦öÑÍÀËâèÅ 3#•õ³d^C –ð¥•x|D–訰¹âŽ•U–±âyWP¦àbØ\ÔýàZýÆB‚—Êú™ÏB÷ îÞóƒ£̉Ó’›P@×Qç†'ïÄ©ûßÔ¤Hd'žO gg`ô/(’ìMЩ H‘•)ÄqS~±jNz™Í´ËcqÃŽòlmbE±Á€\id úZÍZfkz=œÇä`Ç4&ȃZ€v§ËJ)A©‘sü\+ÅEòä3:ÿ XÇ žMÚ°Lüe±ñ”Œ‰¯ÜŒÑ—Øç©In3Ùm%=i®WýK¥¤ ïá×x¡Œ/¹×–kkwD㦒•VU æãt+_M«ÃçqÆÿø^YúÝcWQ‡)wñU¦YØÂÞs_…BwùèE¦è0×î|!€ÜNuÁÑA ØlÇ‘U€g±zÛ³^Ñè ^èád Æ T tE|°¸Š€šÜŽƒØë¿âpƒ0;p“KÌÿ«$wW£ÙÑàç?¤ŠûÃmç l{6 ½ÅDů›´púcûU§9õ˜¾½CÄ&툰œU>ªËè̹#·ŠŽ7ÐÿœrUîȱES\ì3OD·ã^›6F~L+t"~ =EÄè÷äøú‚"ó„×ø8#¥gª¬¹m%þ }·Í¼UyBeØ,àOW'áä¡°Ç׎zöÉ›dKÜÞmÏØA!½ñC?þ ªó²° À‚ |öÿbaBÅ‘GŒC*ì!Y9’_®å»Ñj×Cìï)H²Žëñîr‘ˆ;•škÁ@ Uц#C]<=ÿ±­'ù{K‘ðF}ìú¿Ÿ"º=…Æ“HÈB¾ú(²‡EÄ+ê×õüZ¦I4P,—.ÍkÁcèmàysòNyšu…ù‚Ït® Ó¹ä|—–ÒÙe5_Ú/#.jÞ¨0#k ˆ†t—3Œ³Bq½[šcþ3ô¨Œ»!R­²†Îùä>±*å4éjMÔDAçypp*ÒŒNåPz_”uATÆÛv:"ÂtÓnä—úa›h¯/ø4$­+·0aŸÉâóÝKAt„_¢Ff XwŠš…>H ÃEY© H áÛ© (o&ö;ÕÞe0Š´*òÁft§Jå°°2–¿aì% qTú+¬P'VdÏRT• ’’„"Z®™'Ü{gÝKkè¯XYà~ U]w(§;St‘®ÆnJÑæ¶6|&â9ŸeñmÛìéß¡Ôq…3{4¯ÚoMóyɪ‰kc]¬¤•_*êD5ƒ¼Ó¬†§ qRPñ jÄVKõV9(ÁèLõˆÍ…Â[„†À½¾Wÿñá¹i ‰ÈǰÙ2øÝoMщ*¡êW³ïrÞ…í¶ç—ªpØUS)êØçÅÖì–”A͹ð¡{ =AG,~Lq êÏ´hÅ1hãÄ(úÁi ÛH!7™eÿà±ßÝÁ¦„“Uf…m‚MŽ´qžûìʯßâi󄆸¦©#»5…,ªgþLz«¶þeè~®:.>¿ãj;!œέÛê­_»¹Øzðž³gFOÌcƒ÷[ ¦áý¿§ @ó¿C†”ò-&PlkÆm—oñÃ=(¡9 g¼Oí=YÛ¬ŠµŸ|ñ¼ÕáaÐuĉ|n±tû¸…ˆ&‹‹©d¬^¨Ô{’/Œæ#ÿTä4…“~çé¿H*=s‹á<¤Ý[¶ ’ q²$Yo÷ÔdŸü.¢U0☡JoßôÖIc5U¿íDOtÉmù ½©ùI  ÿƒh\SÀÚæž4[~sV•+3´ÞŠ54©.Er*î×?z 2Ç 3FD¶&ó µ¯fdGf× ŸØi¤žÜw²Š¹n{”±/íz Œ`¡,¯L°gQƧí—á»ðU¢O×9!RSÀgƒßÁ ñ¼FË£§ÝxÇwý+„ŠU~aÍYn'ðÞª½3» ~mª,™€Ô LÓßøÖiU6}êFŠPEz„®½‚§¨6!w1Aµá¯Š®ïçÅïµ8“нJíÄFi@¿¥Ð6ù›1m¢„=wo¥-s²ÞÈNc3ÈÇ !cGL”¼êêùÈ UЯ’•üµ>_|÷7Ö…ÌrÜUÙ'\9H/ìtj¶Hã~ñ3½Žä’öm¹0Ì—íaû|Ê ²¹Ü¤PÔaòêðr¶3±«üÔ㤵±›B¹ÔUrn2õFæÅ-SÍov? ÉÏtÖ6n@€.&ºD_ÖT“÷PI²iCêæŸ+6†ðKƒ錼š ?Ê3Ø¡`¸î~Jm|Üä¸rÇ{ iÜÌÿ‘Ì­ ¥vûGëÌÉNyî±J' %é‰rStúIƉ~&’«ú|2ÏKGõÈ›iá{’<´Ä¯FPúÞnÞÚ3ðÌÅ–*—µ78²ŠÝ‰hï"­ #³õ'h1û¬6pÙ­ðæh=éê ѼKtÊeŸ5b¨ÄiË@[ø[suüÃi)YΘﮘ!–ÖnY$¯ÎÃ"ijG(u­ä ä6K¢;­ôØÍc­¿ÿaÖT(±óªÄ£«±õ/ üö1)µ$&3ĤÃ9@‚€¯¤ôDö•Ül”³šÅ–ÿ|ýL4k"÷ôÂTs÷ImD$}  ŽË–]ÇûV‚ˆÂ  2 È­âlöBÝ'9©És:O›xýAF0ñ‹¹ÐH¤©$ûø7Bua+1C´´žÑ x«Ì⵩¹‡6¯ÅÁNO"Ré›qüïÂÊÖT‚Äá”ô€w’R•œYgHõ}-öC'ë,u‘-M1üc! $j}ÇK“}–öÖú_¼è§nÍÑ»h›Ë÷Ïè¨È”Œ ZT8ïÛs9é¨ßfO™i“pßv÷ÇÏCpÉŸy$dÙ/yé°i8:š}ÔAóâ©ÅêÏlߊÐh‹ÈõFÂnSñ¶ï¡E郬P¯±Ã¶¢¥Þ¬Ç1\šÛÝJ5¼à@ø…€Ü=0šÆ1šw¶|ýnyÉZS¢)KÑòý¥;éóA‘Z°¶çÍ_ù@¤”¡h FæàAÊÀmk<âŠCR9ÒÀ]—5äMêþöý¿;?Zñ׿|ÞŸIg˜Ä2å/]~F%Ÿþ‘Àï¬ÿø-ûRªÄÇ SÉòfؽ”~ BaÇŠQÔåDqh>D`ãÄY®é#P8¸“þAÒäsûñR‡Ãb¤°­wY3abÿGÔá‚3‹^²Ð„S@UÂe>/símtA°å #! .È27{~ñÔº„þ$ÞZcåªÏÖú#,þ\í‹ÍKÖ ¥æÄ¹ó‹óQ›@'c¥Šp€>*cêi6¼¬"ܺ ôºÓÇ|_<ÄÛ`:¢™j  ]"ºÞûÞ„çà-Q9{DõŸŒ›gÅfÿ@‚8p¼9ÞLßËæMEåµ{Y’Ÿ\?Ô$ÑÙøCÓJºKß^׺2ïoòo±Ñ„^¼#5ë{…¶üÛêšS4 § (™BkŸ õ¶U:YÛÅ„ÆãÃ…¨ÚêiøÄ¾ç0§mNžÜiü}í–¤Aæ¸<£%J¡Õv £‡¶j(¶£&Ôã vJÇReŽsÂ\‹^ÃkŠ â͆%§E¯¯jQ‘ÖÊK ó(KlÔ×]¶áàÓ…ÌÞ8œ%ÊÉìF ¶Óƒ¦P|VT¼${v·©Ö‹œ¼OÞÜLleN^lS‘_MgÈ#yíê3žá;#Žxt›$©üëTpáIØÁ8RÅl­ÊŸXùÂ.ç2é})Ë5—°G²|þ’Ýó‹s=<Óhuê=¢UžÂßKßË3.æ^GÖe}+×T( ¤¤ß¬›¡¤êczÆøYY†³Ä¤ö´*'r=\,¡]d ³‰?P-T‘FŸå†|HàùÊgörVœ‚°)}$¾Ýé,âïSóiT¤Ñ—Os#lèšôSƒýÀ¨œ‘,Y}ÖÇâ”IJ½Xžšs›UvdÏå8¬ú]~“ðê Ñ@’ÆÆ*O¼]‚åH‡ûþ¢C¯p»óç›w¯¼“n:"– “@)5pLh>'?7û0q ™-Î8wjåbÉ{®¥¦p;ÿIr² ø1‘zWoÏ·/Y¥Ã<>,~­ˆ¤:Fì4\¬ª •ã¿[ÝïüO5:ÅÑŠò̤åg‘ êOG¢Üæ% éòæ\{ýÊQu,hÔ•À <ç-Òî|ô ~m_ “«ÈªEöÓZ#%¦'Lõ $iàK‚WhtÀ-fOˆÄ®½õMpˆ¼ƒ¹Ì%\´Ú•AvJÁˆ`-ì.—j0uwéÁYìþžT'S‰ñ± :™ŽŸé ”£Â`¢dä&™‘Šÿ²íV`³+–ú­S› «‘Ïõ๵½þ Ëݲ¬ ÞŽÈðê#= ±›Æ7”—$—4*Ã3ýÛ"Šö´ÏI™€nË5iüÁû-Q.3$’¨ëê¹N*«&’qJot$,¢ì"6f©h¥VÁ…üæANWÙ Ayñ/%»™ ž»s¢Áe–§wg|hìÚhs¾(' 8˨ëDœâ‚ÉOõÈj¯>qnqÛ þ’ŒñàŸ'Ù’zØšô4uòëØŸ¯`Ô”ßT]X(bM½É•$ ü†cÜ}bnÜ™¨G¾gÿïSØØòWàU)) Õ !œ×ÿ®Àà ҤŒÙ}U/zѱ`ÈCì. ÖZº¥Õ˜ ÂŽMtjÓV{7EQ¹T¸… X*¡[Íè™H0‰ñøQ‘½Ò0±d´TLAðÎD›Ö3¶dúܼÄ[ÃúM¯Ñ ãz½­Ä²þ«¥˜KÜ΄džìàÊÕŒ4Ä6¯}¥ÌÀýlævª99ÎÌø(Ü“˜~ ¾ÚqcÒ£ ©kyøäRÙì@š9Ÿ¿ÐÐduÎ eåé”_’1ýêXú' ¯Jè˜_&Y•Œ.þ\WlqÞöŸ!?ÿÕxލ„ÇRGµÓ ¶I¼²Í)D„· îbÑã©V^ŸìZ™UÎŽºÜ@;ç ûRëAá´QgÐgÉì¥L)ñQܸ,8ÌD%ÈPæƒãŸ^yì6å¾¢Ó/0­àèLKxOOM,@fžâ=î+(~LÿÕí¢qÍ7lÍ(•ÁœÃ–(6¬Q=ýfñÏPKÒ>ˆ2²c!¨?üÒŽ ¼"¾šp¦ß«¡¼¾öÐ_+œïtŽiZPÑ‘óc $° ÿébúæÈÎzã³ø¡´Ì×4è lcõ ‡6®¹k ¾ '®¼씜–¥É£cùˆªs‰÷]Bú¨ùƒ%þ¹A8liXÚК[K¯+‰u·÷ݬ۹Á‡*A§RdÓO•Y”+ƒp_±Û’ý‹¶[é,c ?ê”EúK€lR™%weÂc)›¾zq]&’‰sû\Tó†éÊ©Ïó"B#Èw•š0¯­-¼Q2ÿ`¼@5ÉqE V3‰0ºÍ”Ъ—ô¾2ðô’œ´§o"Y\qŠž(}ùP­D€ñ?X _ºCÓ<‡û©ãQµéóÐʨôï&ø·v€ŸpKtâ0“ ÿ§«öo¹WwÍÿw…Z¯by©n7$Ï|_ž˜ù#´ìÓxÉÏ«ˆ´qõh$‡ä#’킜ÄË·½g¨zø ÍÆøyº‰¦˜mû_¤eÝU³ |Kñæ…®±ðŸu¢{–WÒÈYpîñ…þq,ùœ¸˜ËÖì=yà \ öriÆvÇ"Újé”l#ˆØLj¦À™Ê#þ~ÔÛ 8k;z ƱØó¿OLd ‘žƒmHH^¼eó£³å %‘ûtøC«H`ÇÅÝÀLš§bãš~£”ò‚;··†¾äϘÙgæº=ŠÑÙ¥-\è±Ûš¢i±á Õyœ¤ïN…QÜHÎ顚>GÁ K—»,™ØÖt‹_¶]Z¥v––Œ@a7Çæù‰zŠß‹þÅSKæ‘ÛÙ!ÍlúéÁ‘·fÌê#:=Îâv,,Œrq,³# bß;#[µ>‹zà”|ÄÈ-5ûÑñu “T¨ëûhÀ|²Xz^þ…ù< qÜæ‹A’xfNòd'G0ŽžËêV‰ï:¿_uZ‚•M&sÿS€V–OÜ‘’0£¯&˜N¶ ì Èê­ÁöCɶ1­ Æ~ÓT‘¿Â˜ïÈõÍÒ 0h IK‡½×Ò¸÷–{· Mýô u·÷Z¸²6ëÄÚ)ª=ç½míC켓ý“åC‰$3ÐÅú¯qÙ¦ú÷n6JòŽ©=6 íÙkû»×C³[$§Û<<è“#®0=DQ þ¨¥“Ua4 _¥ÁØ("> ä_qWbsU¥D‹¿§œÇóØ.¹.}–äti¦Hz²¬µÄ¾ ‚ìÆ¤“#TÑÌŽ{æ]{ļž®YaÂê—lÙÖ÷žÿï8@b =NK`CC#òB@~QÙ‡îdÔz»G¬ÐØE^³ kÔÍôß¿AqÀ—Z$.ìË0‡—±’0ðëæ” 5d@¤8e¨@C5»X¼4ˆ¹5©<ϱpDı4,¢—GÀ-îÀþô>ôóMë?¢WèuDØ×Âsº {Óÿ‡eáG-ìÜ þÓÝ8èÆfðº®ÛšÆ!þj™MrÊņ¿ßÚµ‹ü6!‡ÃâG³º@|gêGnédH`"UÀ;R¯¾-å~ÙËC;ÂfÞ9c„–‘õ•U}lˆ–‡[ÏŽå›´~_WM4QîÀ$‹pbuˆéÙ&’E:¡ñÇBé®û[/¡{¿»‹xy4 ÷ qëWæ°>¤VîÙ léáË•;ÚTwQ±Vœ¼ ^e*1ö­:‹3½<y]=[AÔAÃta®Ãÿ±U»?‰qµÝeÇ@ø„N>à 7`Ì©ž£8|Õ‚xÀ Ÿðñ!Çn´dà ºUô²mxì"`væb1Jˆ}e 8¢OúxÃÂøڼĠ8…ž²î_Ï-­^CàÖ½9.Ü7¾[hl‚kÈaݹگ‘Ø_ì3ïƒgTÆÏi§p¼áëú°ïê¦7ã3oúÈK1»?ÙLK;ì!jõÿ¿Žäº…Ê—tïSBÀþÝЪ«´|)ëMrê–?\ 4˼T¯nmĹY€J㿘BZvÒ½[h91ÆÀùýæŽÄG¹väb§œÅxo»ýÎfƒgxÍþ{Ö—ª¬ñWpÍ’_ðAÀ*Ç©qQÅsX. ÕMóŽi3—‰=KÑdÉ më²"Êwr®Ц÷Sëý)J•|NåX(Ðd„r§ÌT¬/9(7ìx‘?j:¢R‡°§µ¨;»ÑÖBâ7¦¼Ìäˆ ¶é+”‹qßuHsì|ƒÉ+CR—-ø¼ž–FŸp뮀vZ;[OaëŠj ‡1Íd,Œ HÈÁ<%wnk]Düc¥Ö$ËÉ¥£·ÅmåöÅLÜÎ3E§ë#›º YÕÙ÷R+/®·[xÛçÉïÒËŽð€GP Ü¢m8$,¼nÝÝ36¿&ÖukXÅœf!o†sÖÞß½r}«aWó'›ÝÙ5R^vˆ?Ýy|‚¸•÷ì¥ãu–¥Þø‹˜6S fíuKø€B»÷)DÔ:ÖÊbàíèýg+{¹ ¿”ÜC÷>³ïVš üŠÚôU!Vúѧë\#Ö _LÀ(“£ÍÙÄÃQ/Qúe§qt׬Âöº˜$a]X‘΀„6•¨@€5ƒï}èÍ÷£(‡Ë£6©‹ ©Cœç¬ùCœÙ>(‚Y"€R\Evö¼6½~dpc*\½º§i ›ÿÃÒ¨1½½æhD–ä°ÖWâJcœY”•z´7¼}A¾Óœ ̼V˜%:HÍ K8BUåµ9$xÁ‚ÐÓ… †\ÛkÄ>  f4¯ñÔˆ?+Ñ­$~4 íÌš6Õï“èsÚžf\ÊJÚ¸Ìì¬3³ië—:}g[[t—Ä‘ZKY†¦µ3Á·¤Hÿ‰N}OEüG–›ñmØú³6æÊCå_Ð[; ®¢}æ=° p>Þ?ÈÉ䫬`âùÑF¶‘á¦W}ÂïºåZ=r=¶ (FÐr`ÓM„šhyy3¯Ü4×+Æg øë~£ ß’¹gèJBrPZ$ƒªt­¦/¢<(ÕvŒJA¤]JUÑ™e?©ßÏ1jÅ)¤tÐ>‡Í4ЉƩ9óÏ~ó»ËDwiñ)µ¬ŠKïÒ ªÓlÊÒûÿ75d:±*ª„N5SÂç•ú”o{)Ï'·b¢Â}•žtˆ~î)møÛÀ6 *t¤&`*xÿwÂ`0ê5ÐaÂ\ÊÑ:(âÃ6'sišç2äœøgH¯/¸³ÎRðœAaÇ{ð%¢jóÏ4H€l.(bqØþÑ8ž­3k B©£‹J{A?ú€!á¯Ù‚Ù·ô·ËV^nÙˆüÇ´ÅÆÂ }(Æ ó¡Ü†ˆqóÁâ7ì“6¬¯€a$ÕQ¹=ƒÙ¨*P¥Ïbßø#0i#ªþ$䙇©™Ðú{ˆ>ÿ(ÔÖÓýµk?›ÙyúªÌª[‘ø/Cé5ïl ~ux™Ðì«Z8<صyû± €Er½Úë…—Éî$›¬¡æ¬-߸D©fãuO—¹¨ÆíSíEëiE0È"(LÿH–ÅhW}[—íÉîØM‡“%® «=@õžFóÆL¥\´8SðÌßb›bFWlWpC¦ÞðàŒ†žk½¥Ñµñ8¬Qeæ´ÎNÄ’®aønµ™þA5Í2K‰=Q6ü0‰)|M»ux<gìrÃÀŽAcgúzE_kwV'Ä›VŸšRÞ9R>Sε¶¢5$±T|B€#d1 E³°£?-^Øú’…!¬ÅÁ)ô÷}üÕ üW[â !&zû•fйæ}—êÃÇÿ?!¾”ˆ‘ž|É¢…²Zé°gVÉ¡¼•¨òC­6/á;rƒ¯ƒ2=ù€Œs*]âݬ;á‰DWé½q TÏE*JÚ¬N~•`ÇlyÞ"ž(Sßm0”zî­aßx¸õ{¡ãGÓ ½'{ABó²Ð!Y4ž“?ã8×€W’˜ïqôƒ¹ÌÞóHyˆÄ.JÎF^ÀîM$æg~{œÏ_Y2ì+[#‘ŸÃ ªJ.bíûZ qÝÕ¥õ=ÕmKyžÓø??ª^s4ÈeyÁ.È2ÿ \ìg¢fô‘Ö—„ŽˆÊ½¸'`‰…ÏÇQìQh–<ˆsÈùŸw‰ =`H<îíSlûÒ8i<7€à0¿£êÍôï®ÉZŒ1<É1åyc<ïZÏ¢.ø 2ÆP-Êy|´«³y5ü“\κÍ=.£Ç÷¯ÙŽ/D—¼‚Å4ûè&”M'lqñ|7!üšÅçô[é±.’”«}p9çJ+Ëìyïì ©ˆ¿+p±ü‡mrVÅVRög+ŸÍKSˆð£zïJJš…OÝÎŒB D+yÉ›ÔÒLÿiÊ433*¹pW¢tOî µ–µ?ÊXcþà²x‰+‰²>#4'í)” ·â whK—$jQÏKNɯ˜)uªåm£žœ¤½/»^”ñÉmðåoó¿ËHG\`4*Ó®2p"Ä'ÜâŽì\9o½ŠÐ½Y¨‰f…-áaB§GÿªL2¬Êf !h˜ìK@æH?ë šC•DñÅÝÔ}Œc–}ÇYeÆ+0ªG™s^¤Â‹ÿ.?µ˜lòNÁ¾â¨§ˆ°£p§½ÂZí}É:²Sbì±C¡ÃHK@d–^<.Ùlw¡:oʼ¤H==åò·„•³ÎtY‚í|>‘ så1#Ó»ñ6r-vÄšcŒÆR“8ñÑ]k} MóÃÀÚ.'q1¹ÈB“}}APäéÿýì#ýÁºiÕ;l)‰áY3ô=ß°ñ8“5ï]‡^Š–šŠj± Üÿl‘Ýx1}côŒóÂã8À¾y2ڊ̇p¬ÁºÔY¹äÐ ~'Üé%Øo\u™7éç—fï‰Ò`C³ñY—tP’+–DyöÒÐ'ÒÔC•–‰Ò6Ðù#e»D7dæ¸4ÔÉŸxÞ”,†œZ´{щ½LŸÿ^rÊ4ƃ=z™\.í`qãC‘´­¸‚H0ºÆ²nvAŽÛøKeÃHBÕ¤•¬‹ÝO¯eäc3o·sJèmÈE=J-[Ѱô§üƒ“FÌXòø%w<~|5 šé1U[G) ±7=£(éP‹RnYP*–‰ªMO-P!7l6Áûæ ]΃0-7 m…yÍôˆÈç.i˜5æZ“À”õwšqµ©Á]Žæil˜¯ç1F»ê]"!öJó¤©Wû)¢”Ò øâÚÒ";èdú ¤¡N7ÿ%%ªÀ“Šzì#ÛC» j{—T°?£kËÄkÁ_SîžéVx>ÔT´"`‡—w†ƒa´ “V2Эˉó €Àîö±«N«›GHGüb“ÀêÎÏq~@Ú׈GVXm$ÀÎQÓ°nPa1ü+˜™ U©]Êä¥É› :o÷÷ Xx- ÌØp|éž–†±9õ ZÛP;à#=^5¡àóR6•„X¶»Ÿ¢˜èäu>Ëä¡¡²°Ss„O'Žß¼ öü‰ß«B*ÁpôFÎJªÞká†**©K±Þf ³”î’•²S³î~ÎÈ9 V?•ré4q~6¬h ê[Y>”57™ØeõVŽ×Ò€SBèÇ+O8rú+ùµ_“Y¥Öî"¸ëåÞn!§’E|ku?=Q°ÒmûŽ [æʘŸ@rÿ1!-Ùûkrõ‡uè$amÜ )Œ,ÂÊ1y2€¾¶šFÝIQÛå±kƒ>Ð)D㵦²%ÄŸ•Ýzá]J^4ðÿ¿=Ü"MK2bëákç´y~FtªŽDá)g¥ÏUhð ö”YŸ-ŒmæÔç"›ųŠ~0ÛS#´bò¥²–¼Ã¿Ó±-u¥µZX¡ŸÑiÂ~™è6±–ܓՊfbK°ÿ—²<… ÔZÚVv’Ìö޹5h2-‘pf;#Nl"ŠÛ-¢6âPÔ©àÔ:Ã¡Ï Yr]b}Dk§»K¬`jáÖ¯(×€ô®•ÌÝ羂…'oÑ10¢«ržT íÅ™Lñ˜bIL·¦uÆa/uMŠ˜.sUI[>u(\²c [šÎcwÜqžËdÝçî!&’Ç>O”«‹]9õü§n¸Ùø°sdòAJ æIJŸ'£7‚™ÊàÞ©/ÙÛJt= ižo%buÕšq£ýg;7XWÓg¿zÜ3ú䢭钸ßÿ;ü}NÞv„ƒòÃWfz½\Xhûໆ¬Š{¤O3 hK®&Ž$Gª:s rVöQöbc8%Uå. Ðég9F=¢À †ñÝ¡'|[\üÿcVpgƒöÀI‘]†Þuq¡šZá¢nhmžÈ± FÖLÿ§âBý¥ ›ùF€n‰Ÿÿlmœ@ÜÜ8ŒÈ§8\°=¼ÕKÇvN˜ÕÿÈ’ÚÓˆJhæ%u¢7(Úãò·&ÈYŸúŠ“í'³rãÒy'àbšì!ï+¼473i¡Ô’oBнÃÛjçÒ»¤3чz™ÁVW`ÍHÂuäoÌƼîþY S4+T«B)Kë)'—wþäE¬óZ„AÅÖ\M+NiòCû‡0Úûƒyå|+¤b¬ç/h#Ð’Q½£Úa’³çÚC„ƒÕ9ÓOl(@yd‚÷/Zšoƒ‰ÿm@9™ÃÄ_Ò‚ˆ´CǼK0¾CîsxÎU*nª~¡N)²™9GéÐ7Øz«Û &…‡‰ø£^:ØÑC˜­,"ëî` G‹=]5Žúsq-èïD?Ƚë¶‹®„-¼7¡Igˆ ‘ǠǯBK"5”@Å»úz&´#{Ï×þté”?~“sIÃ=6‰èc¨êÂÉÝ ÿzzíŠsÇKßÒ´Ü qÞói}Îé47x„¢‚zÏݶ¹ | »6%‹=”™ùñdií0«Çc1í}03îDn4 f\'g ?e´XÐByéõƒóý`à•™54NO¥J‹ k“¾¢I8F³¦Ð¥ÎÈ4°JošÌÑ6šOê0dË…ûµ‘úχIð! ŽÁêØuê-:Ÿü ÆÕ{¯‰ß—‰ ñ¦­ÿñRñ¸‡!£ …åž %õ Š  pô¹+j¥=¤¯Z«Tš.=q&\OHö &ª¡¹¢Kžddö§»V¹¸Þ£(v£\¸RïL²žÚ€Ã}[œq%‹A¯ûK´3œ]²†g{=S©wÊ÷œ„è -~~g3mÏ€M[«¹ã„oièòý€ƒ º\>/¡D3Ĉ-Ä"ã&‡Db×0A×l&˶àW¾é™ƒ·þ&˜Öº4 ªÞùqŽ7éŸ&•nÝ#xš,‡Uû]µÅ2œf êâÆûCâЖˆ`°Š/æÔjÎ@D!›Þ¸<~ÔÆÙ×\%a;™ûš_Àeêóä¦5–¥Ê›ù "H—ȰüoBÅýë‰íEÀ”#âé¿}×3p"“ø4#ÊUn# žSqúí0eƲ۠¹jéoñ¦%«ÆÆó³6Þ[6CËWÓà!¤¯äéXFõÇ£6$2DŽô‹m¢vâÙ äpûùS:ÏeƒÂšÑ¯ûü*/îÉb$ÊͶ&×TaR=“?öÉ®<Àè «u§Œ—:7OvÁó2¾EÝà«“òÌ ªôK"{€2M`]3и„I¾ªa¨)*çXŽŽ…¼BxíÝ`æéÔÄàº}…úu G bc€¢gøYâºW¼K;Øüì E*‡CŠaUФ[?Ás›G}ã}# kÓ¾\2yýÖ=èÖ¨¿©>8w6ÒôY‡mô @s56ú"R*S×µ †8eÃ>6¢»kÔ?ÊPY_CÁ#ïß»\—a„˜±‘Gø˜L[JšÆ'ó®c7gÎZ1(Rsúï(•ÏØUëDœÒUãÓÃõÊl´¹—Þ;f„ªK&:„lô)bœ–ÅÑÐÜ$}~vΘ]oòŒÞxᆤšß1ÔYÞß Ç•Øä´õ´ÿ½2„iP!èíî)rG´Äˆ?E¶²˜JÃ\êÊjÀŽmô©¥˜eeû_9¼maDÏ”ÎÎÞ€Þ÷Ü3íš~Y‘6ž,r6±Ò ›œµj·œÙ®Qò÷Ð=!R+c®:Ä Ë)§¤(|ºFº÷ämš)bŸ‚Æ‘½cÌ¢·µÊÈÍd€jG`Ú=.Ú"„=8u QÒ7´¼ÑŸXÝYú‘\á¾¼ úQ䀂ht:ª¹¢EÃ$ÉÊádæS;\úù Yl›Ÿ‹Gˆ Öãžâð—äµ5 Tþyø0©a1áňø‡ð: õoK{îÎíÐÿârÞ ©‰b¥Ë߃àkÖãRL=¡÷ò»f²«ZÜôbnS[:ôé³?Ë•{Ô€b­v@ÔjIJ¬ÝL÷]Š}ËŽÔR7øÿoªÚ\öhÛtê`~_«²ðÚO¹CGñ3ôè¤bCØ«K DkáÆmž²P£¾6?3x;tÓwÛ­t‚á¿2Xrê¸ëIi˜X6_²'·ˆ¦ç’]<Žˆ^Gèuâ9Ä´@e`  ¢S)€ÖTìC8Ú}fÁÓÓá<À4IJÂÞÃÛò6c^–1xÏWœ÷‡Lãü3—ÒhQÀeÄAÚZË|bT¬÷˜ë zaÖi);µ²ò×½¹¨kaX8YF·Æ' ©ñÈ禱4Göu0½s4vý›WQ½¹pbëžH8a›ž$ÓŠ%¹™ßT¿aî7ôÜ·œv¾äm>ŒT á–BCtüŠ)PÁñϳ¤EL-y>Ç4ÕìÆ®Š˜ãRéî{™ZH=¦ëAGÌRë(‰öF8â!5Dc8Ö²Œ¤éÉÖ/Ž-žžÝ¾éŸuÀf+dñ¥2›¤;¢‰´šú¯vŸ‰j«blèq<ƒzöØ„‰3Òaý ­±¬cË[`› )ijw×a¦71uÁ™Õ’Ц@¾æBqzM³ v½f™¤µe#½†,‡÷Ù…[€P~z´¢Æ‹8k?j%ËÎàaS¿){Ÿêé N–x÷;Ébf€_ÁZc ­;©p@v¨tº­™ βËDŽó×:Ç÷«]ïI.@ÉJÀÆà-AæK@Ë=¡ß\…Ö]®‡ )D6+ËŽM¹Í@ðÆo{ 4Dd %DŸ8cò‰5ìèâ3"Ÿ”iNƒ+ ÂCpp準z<Ñ*¡%å3©"¼öåôT°§T¡ ÙjîžNt4û–TDWÍn›šè¿ˆup›:(É¥—ñ*÷zW£ëèÑÌ@(3Ü%§§ÆD VøÇ͵ë"ÕB8·.-÷˜8‡”ZZh1>'úUw–w‘—€ÅÆÚ‡ÒÑXo7¡±Ñk¨îû$¥“<`×MèdÁ {[qEUcãuÏ›ÄXõQHÄ]wšçPÒ3g·îÅÒÑ M)‰JÅdKòjhžhÕd̮ŗgÊMôìËP,IìæoU‹g,vÜ]ìh«‰aÎÝgl_àÙÌOu?²Âcj€F ›xaŽSo´r+h²(<‘[B¯¥$}àÛó;¤ãùb­¾lòºß’e ¤Œ¨Íª"Tv&öî*ž3&²¹RâFòÑ9Ô£‰Sb3C@gµa秬ÙA`éï3àoœ¸°ÄZHQIüÒ¸g(¾Bõ£ y'Š­}1·®CEý3Å…ñ7y¶¨—]21_^—^N´~BÏ„¶Ã7í³ãQóðíŠX²hT zƒ P­É=s¼œ«Î†/¼­…—E¹'b¶ ÂÁà ‰º“\+X׃D˜uï’©Ã âT8z½ÉwÁWîdb¦½}°EC^Piš-³‹ Õ¿­±¼ºÃl£öhPu,´RE"Çqû ɯ›œÌ”“àf ênв–& Aú1¨: æ—ˆ7`£ƒ“`TPáaÚAN;N_ÕB¸Ã±hȘw,Iø`F¤­Ó¡†î[\;MAxÎ>N/uØgè¼PÑ-®ëpR…`9ðžH˜õXÞÔt½Š´Œ™éÛ ûÕö7€|wó‡‚ìïæcÑqÈ M¦ŠÌ“±d È=‹X…ÿzrû.C+ãf¿Ð}]qöasÞ†¿‡ÞáÕ°yš¡Ë _Æù2å,ÊȘ¨¢/µf¯FtŽ€¶½ˆvû7²Ë¶éó6àËíá{0Ü3—Ø*óWgçnˆÛJÂ[îí¥Bý^ÆÚ(b|ñ¯¥XÛ^ƒË|ú€_œ2y¥¢šoS’ƒÊ}á­Çƒ–Ó°A|dîx±G±$O7ˆàî‹¥¨•·üÌH¨ÙçÊ+‚Jp¸ìÆCý,˜–Iµ$fî/³t±Ú¢«¹ŸP&ÆCSµÏj …1~Jçÿ)˜×NÏ»NTªX'W2Sc‚¡É€ó+E¨OÒ}¤hék àÔW#ÃÁÿîáTU…ªáÍž3Ë=)¦KúÐØqøÇºÐá(/qQ-º uëÆºŸMÊtŠÉÌþ¯«„‚íðÒob}oåÆp0¾û®ŸâJi~RGøòûÁ7V&UÞ+³]è«<ŽJ‡+uäd`aBÈ&^wÒ“½~‹z† †.Žmø *K²ƒË“e¡µ´kìpO [q¦3X\[2 l<5HÓ¥|uã8Æu ½FŽ)ÈœæIß¾áMöù´Qªú‹›Å¬ÀUúˆ:¦n£#@TÍ»,6ÝúßàßhCÖ9ÁÔ1S@/=$ðD\”¼í<>®¡qðFÉÛÎú÷‚lcÒ“" ºÔ¯mÁÓdý”Æ>3_輂 ü.ÚÛ•¯ÙÐ*¸Ö“ÂÐõS‰Çe€3i¸­Qõ|5òÙ®Û}®ÿÞ¦Õ†MñÃ’#‰ÖÈ•ua15‚§äÅCRÙM‚ –çf²c‰ $®SG@,`çÔëfõVH’v@W'P=lŽ dn“ÕyS8€^‰o¾ ÀÁkÞ†òÄvRý§o‹³6O‘©ØÐÝì\ô×2w[EÊaµ2ÞfR3ÔÐ0]à¥Z㽡k)·ú® ÷æ YPüßJ·ŽJ†S0‰ v*Û˜ä³ÑP[@@ÓòuølxNµÆ×sÁ]ôü*1“×ûp[[;J,kW6ž‚û½¿fÛ9djf¢7 ܜ_}8õHÑ«;žøÁß±Rªõd[¥ü]ªsšóRÕñÜÉAéÐÚ§ÊÑ9óÖX§¤N0çN]ŽvW.l8QQ(Ã7õ‚c†ëÚóñ&X¸²’]€ø ¼€}‚Ï1Lû@³¨2šìˆÌöâ”"V(TØ£r-ó–)©é˜ÅF¾`>׆À%1ÐïS.¼_U'~ÕFÏ¥²‡Þ¤1·_z¦TH[ú»Ow;öSÑþ4ˆ6šÍˉ‘¢»ÍŒ¨•–õ4s–¢€G5¹á?½Íì£ó‹Û掺-;zÈŸQémd¡ÒIßÐ!D‚‘`<ŒÎÁMù ­T %Yè$O›È’K0Mª[§ ×¬wR’ÝÉ% âã½ñB# #—TcÓ <–Hz}×9¯¥¡îTlB«ˆûðEN|üá ljê¶J“Ñ^Ž^Ø%£I½@ÚÞ.X𜙇þ«é@LN¨È]e¹¢k¬G0³HóðyåÆX÷¨ð´[K±<ƒJ´Æƒz‚ùÀ$p¾Ê|EN²T‰¨è„-.×9#vq-ΧÎbx4Œ Ò\nÚ!£y­º§Ž  MÓHà?§«k6cYÄ>É´Ó9×@o†¹püæ²6[lŠÆ¿³éj-mªÃËcšIbëNwžéࣂÚv3«“ë=is:ˆà‘Ÿxƒž<8˜­ ’ 4HFÞe-OTøã²'0/üõ¡íä΀œÐÓ} ×™§¬Eæ‡v G‹é¦ ôÙÏKe!i¦.Ø¢£ 8a=|ÇPõ«JŸ¢I/˜’.]úê]ˆ5â¬ic›ú¿¿œ·ú‚ÔP°¯ªÐ¬>ô:›îÊæñÑR,ññ޹ú¡ýÖ×Öªí=KìÉ#‘H¶X³1!½´' ®£¤@É7ô¼Kõ£kÄ îÂÒþRp¢æ2à JÃ#½¢ÎŒfKɬ­af¹–ZÜsH'–#ˆ'iÓ¶Èß XúyÈ®¢ ‚¡n~Ã/»ã5B"äT¸ÀâëÉ‘†|Áe¡ÂºGLaLDBm´Q#¶éRv³ƒÂû1–‘L0à%º.šdZÕxüÃ÷;;ÒŒ…KÕä©kZZ¬eýK©vÝËà¦A.sû Ï=a¾çT&~îeúêF“à\Ü›Ÿ˜Ã‰—ššÍ¢Ÿ¥%Šg]Eßs°y ”¾Uu‡PŒYVŽbèÈà>u¯pl¼Ç–‰~éÉš:7Smูù”8¢ˆšø›`zgm ½}ixQßF²a” ‚ôàµFU‚{‚¨óQè¢ÜZc]PÇNÌýX´m(1š)’H™xb£{“qá úé¬DdxlÿAç /R¼Úi]µ&–í!n äú^4HºI¾°õå¸übòr££E®ï\ØeÕ |Ú@†€¿8Ó_ÉBÎ —Å$Ö'vX—äM›OLúßN‘êå­TDÀ D[¶JDõõX¥DÎ ù;û&ÞÙø$#L–ÀÝ;fÛás2æè2Æ,–pe ê Ø`,£ )ÿ šiD›ÛhÖˆ.¨¿­"Py`A´žãአu­JNå¸rK5Pj› '¿/wS±ÓþÏ¢¨g•œA÷)¯Ùð¾ ùäêgGóuúÞG=&šýãâJ_•Ë—Æ 5Ïø{v rü Ç„÷1b}ÝõO÷¢ÙEegA€ç¤ËGë‡ÏбÖïþ&›ø=—ç^®8høq”±äwÂSÑ„ér8wã¡M³æÙ)ðb’›¾ñr™­— ‘©'W@ÞF¥Óï/èõ+‡¦œ¨âltîZ ƒËÜŽ÷ó8¦]}¦æ‚ì”ß“V·bHü[ hS'ƒÇÖ—òÒ°®žõZ­Š†LÀLd»M\¢8ĵˆ,gq)`(öEŽhõÿs¸70,gÃXN¢~Ÿëz•LªŠHÒ+QÂVÃ%×¼¶îËcÂÚ…YŸB,u«Èú©*EFÖí[¾L¦Ï–邵òOXeÔà®”¨‘é.AÞÚŠ è¯ÖwV/Bùœø HÖ±›Äü¡‘¼GºÉÒ· s„¨Ð †Îö¥Ý`è'JjR³B»¾–À 5¬È^mpo˜¡ÿÔi\¹—E^ÿsÙŒ™^–oy”5 $ä°‚-¾‘ßhšÇ¾§•mv†f½;@þRÚbÖÅÀ¹µ/M< /›÷®ebÈ|ì°ˆ)0TsÉ‹éÙÍ3ø7k“oeúCªÁÌ q›âH»›À:P¬ÎKÛà¹ôêuãW'+ïS8‡•+/€b7àóö¿ûX`JMë'_ÌËt«ï,BêçÌPYAKfddÒ«¯)£Q2TbõÀ2Í÷# ᇺŸœÓò0A—[1ϾÄg rË gäJ‹Åg©’’0#)8P«:+ñOzœ×‚³ã“QŸÐe0šÞÿ!÷ÕØ¾¸ÊÈêqôÁ "eÆš2G0Äh‹tÕYez±h<;+åÜßD$°t›«úš$I¡S²k …rpl9MTùi>¯ø7(.cÎE)¼[É4~B wF]$5^¦¹\CXןõ°J±rv m,?ï¹g¼ °ÊýGkÆ@/©‘üÇ@òqÕ7S—Ôe¢éDš¦oàXb£A©ÔÄÖ°3ÓD'=aÉ)MˆÔêh°nT/˜haºÜÇsZÝõ¯?îÙß•ÛVvkÓƒ}£óz*ñ›~ÕÝGÉ®ì¼@šö‹.SÒKìB%E„ó´DÇ ¯-#\Ý¢ÃàÙÌnQ}L;êìçuçv˜g.ÅÉM%ÏH¤ k¿9ƒ(§â†-|TÊt§tÝ*³ €U =2 c<[Å»÷P=ªZ·co'ðU¹˹^y¥ƒõ·lÝËR1C¡%¿³å=P,¬.Ž& rªEŸ™–ÌÐk‡–Þ)æ“2ªó²€sÀWÀu \Ó1<»ª2N 5Qþ;–=mBþ,®Ë"ð»“5±Œ–›÷“Âÿ_2“h{/6¦™}`¬.ÊÜ81Iêè‰^¤ÅŸ¼VšÜrj\"3ÿÍ\‘¸³ýALwé‹"ŠIÝw•Ë>É~)®:l®=qK}9\4çQ»ô]PRã²²ÉFóvÁRLë)tBg©ÿÛ.ªNfé^×=kÕßðÅ5šŒ5÷Ç@&½…25L·×0\5!­6áÝjÃÅ.;×ÎF3ygËè¥?l(¯'-f¸$PþÑ)f-âĵN¹Ø_r†ÇÜ– }Š"ö>·Ó5 UsØpUA†ðævj½Åƒ¯¡[á™ßõ>uùåÐÆxiÝ(MY ùøMeÊ*F G¶ìwO3M¸ù*0<%j1ý6b0ð*èÆM¡@ÍQ‘’:<Éü×½ON =S)ãEcœ…By™œÜ1Eíõ=ž,z f¨8òéÃn_Ž ‰È`Çœ¹>“ 9/Ì19(>&¾ßd×.˜–­8ÉZ|5ºÎ6ðȇâpG°.§¢8{Á2";õ‡Ëö\pmÄ$´áÂÙÌöÆO`3xíF¹ý>õA{‡€SćbyõóÛm¦8•៊9•qž›Å"SÜ¿ö| üPꜤrᾩ³÷•âèîÝ "ùãã"ˆãÏA¼œ@Žo¨ØæÆíœÓv% €¬cìØìØØ±í¤cÛ¶m۶ݱ“ŽmÛ¶ÝÑüë¼Â¹›5õuYUßM¹i+¾J¸Å°=ìío[º~à;Ót˜~:o£»²í^ûv¬qdH Ë/=inú®`@²kdÉlÖ°§;!Õ9ˆ²¦é——Rƒxþ1¦!F›RBÖb+iÔ=«à‚¡(æÕŽVtãŽNI7Éã{`ÌŸ1L“‘ ÛÌ‘ûü&ˆ5KKêùU•–´•ey kùn…«çBæ˜4Û›yÛ6Ú[ìñ0νX~ÌÙ?”‘1˜Gfˆe,»yì®;&gw·µCFJír´ICø´·Jû!]Ïà+qì(GYCi`¢ôI§‘ó”ÎÛdc«T¹aŸ~?Rá2U'ÎO®ñ¡zÞ5dTøõ!„˜oˆ|´¥°êw`2Æ\çÈ” }ºã½0¾;¯A_ÀyÕ¼?ɺHÛoØð0ˆ(P¨eKå#”–ÁKJ‰g“™ëæf…íÂqF¨PNÿ(‹Ž®ÒÒM‘ ÞºaU‚ЀÙe:Õ¹Z™-ÿfàF¡(¶>/r ³¸ FáK$´ÃÆ9Åê×+naiÎ*‹Ò×€ A(|{¢ªM¾üH-¾1¸Ä ­peíiK—áñ¿¢)üodo=BG FÞulg…¸•~•¿¾™¼87$sš‘þ3žqLÎU„1éGÏo(QªsîküØÓ½zzl2œj‚Š)ÎÉÓ†!Œ“2ç`z³û¡«Î mA¼­k—,fœbÚºËzÝÈ/®tbvEÆ ˜–‘î>ø SÁÃÏßf†ÃŒ[ûêo®¬¢Å<ÉQU¨/…¶c“™+M.õKk*n¢4­8zªÄôw8lØè=“üi©ëouQü<_ÝÁ ã•MtÑ ›;œ))“‚pûþ½ÏßO½¦{íFǸòÒãv08ÿo^Ô|l»‹’@°õü^~èqÏís¿oÜõA̾$h3ž:hô˜‰‡Aó+p—ï|Ä%œû¡&V·9üdÑj¥3¸1rüÑéÑ&×n!£\°·'“;¼É7¡9ðG(" Õª-Y8£Åö½e»FÍ€uÀXÍCR}PÿÍ»qä¼úC–š<èTME’Úoß/ø®¯ÙpÀ=òÜ!æòýè,Õ’ÕMµÖò©¹3¹`™4ÊÀN¶jio;žÈTž‹LÃ2CWê¢éDÀiÉóÖÀ¸†sÚ8榔Hk›ÈRUò¡¿Tì×§&L2ˆI+ÚcqÝyðÖ½g(Fò×ÌÝi8e%ü¨Wƒ¾C{Vžm»ýEóõí)‹]ÆM:ÿ­²™Ic _0ìââ«wTÙÄ‹”~Ñœ¸Àâ»#3ɑזvô W«ZIà­ò¢{ÀFå®h½C7,ì’ ß)ãd¿–ÎG1E¿CʰZs!i ¨í“QÆ‹è„Êíyã2¬}¬u¯R’!Ãbý¸¯fD*íìk£#wäX×üòѹXòèr–ŸƒÐUöiÐa²Ì8“Q¢-8”'>%ÇŠ£ô}»¶Ã¢q ‘ÓÆò6êBÐÄ®†?þ•6 ªä 'ŒN̬Â3[y<<õ÷Ý)äÈ//¡aмî”}—‘ÜÁgžWڑĨ®£|þUvÆî6ýÛºŽï¿ÚFæº,r~àuÆÒùç8Î.úo}{D>UÒ‘ˆi4„±¡2U¬…5dTÏBÒX_Æ…×·Äik ÖEÁËâµG¿XÓ -Zë·o°ðÇ~µáüü¿käOêïÜ™\}.A ´æÀÊctfNÑ®†ï—² 9í@ØØ§†½©À*Ë$Ÿ$ïéje&FºV‰´ý¹¾WOH[–÷ºžÊ"‘¼‰‡èvâúë4²¼s¥+1(5¥føeshćýÌó¼Å‚y$;Õ£ëg~Ò0›œA›‹‘.Ç›™òŸÌ:åtÒ=1Ÿ¢ 7ô`;2U½úšíDM½6І:C­Â?PÇG‡ï'+šò[!•ª}”ë²ýr¦=¼Vmàpä{xXhS‡ÉäüØ47\pCí2š©$áXÊíñN=ü PövœÞB¤µØ@±í z½ãf…½¤á_R?™:QÎG(»¦_ÕÉ ŠVÆTHlJæÉ8¦´«Q}*‡Ì,©_‘Æc¶BB¡#]Ÿâ*ðd¯Œ 7?…Ø;+fò#’pïa¤=ÑDû8²H ëêÛI–õÏxÌw2:#h‰BM¯l M™Î3…­Tj UaˆxÀ{ár„¼BÆ® ^…à»Eæ|VØ£–å=è&3kÍ*ѶJK´bžV¯§:^-'¼¸ôßàT*@Í! /œ °ˆÃ»$ÔŒÅy=§ýì½Í:tZV†fºÁ‘[_ȉu¤ÃºûœLq…›N^°Né:Õ?rÐ|ýTÕ{F»ˆ8÷#Ô#˜e–Ÿ›çNô!²7¦ Ä^ÿ~°{¤$QïŸEZÕ8YBg‡ •B‡õ_K:ß) íö†é°¹‡·-qæŽ*uâÜð¬(dNÙG½áFb2ˆnh<Ç4Þ‘ÌaNÎ¥ià™Ì'Ây|Þ…/ݾA”KoÎm²&O³ª˜•lglêñEòUDÇB2#ڮɻ<áÈ“`y“k²q¼5‡N*v>\Ö)£—ŒVÇë¡ñmyç¿®2_y<²Ï'Ò1×Çxþ\h35çâw¾ð鉀ŸAäBåÃ/è´Rì)Þæ¯~¢Þ­wî)Èoè8aqµŸÉ•@›sÜv[·7x ƒf.à8¨XÙ\aظ3llî;§¸èÜÙßeXɸl.~—õ¨ø|Êy§¶±h?cºË—í¢%"ïM] "]ëdÞÆè¿…Ú%¶R1PÜÆô÷¦ {ÌŠP 5áá¬Ù¶-RO=JÓ!à§Ê‘’µ±a©]zˆ¯/ù§„çiHÀ•¹(ž%êe™½M<‹ Ž9ðÕ½™ª‘#Ô2«¢ÎUKÊÉEÎZ–¯D‡p¸ ÷S9fDÕA ¥hE–„‰>ÅSKâUéàœlŠ\no_‹Šžö-çzs0o?Z”03åÚI*Êü _cTòJŠu‰”èÆÏ©À½¦5˜›úë¡ÀRˆËsU^2³5‡æŽ 'bÔæf´šÞéÚ´Fdz·†˜E÷𹲤>…7úÃ'ÓÙñ .Pò4²¿ªÎ̵3–æâ‹;ddSÖW!„Ë|ãä³¢ÙaŒ uÕVÚLsn+mœLò%¦ûùÔ¯°’°Ü‘ ú°Ln±÷žå$RxÜ—v©ƒSV¥çå–Gñ]Ü+Ù.Ýsú‡Hyþ¡ArcÐ]–í‘ÐÎx±ßèÝ)hXÛ‰£È}—Ϊ»tÚ¹¡Ý±¶©ËÆ"Ó½G…sûhèt©Š‚'Z\nR·—2AUïߌ2V÷F:aüÔÎÑ•œ7ªþÀ'ü0bºûÓ´eP£)/7q7ðŠêsLê×Óߦޱå|¿Ôzów„' IPš~ÿ{4ï©^CäëujÊm!Âç&C¥4Œƒ¿;X÷/$r LE›í ¬@Ùæù&–ÄŽ­ƒ‡VÒ°ùTŠÆ«»ßZil1ê¼ TIY{^UÖ¶é1ŽÆä+'$5pæL(ÿEnÒ>?ãB0ëgZ¬J5CíÍMíX<‹6Ý*ý*²”.…Ln‹jÆæ   ’ž”:jÝèôÆ=³¬ â1±µeê±@­ÇOn ]/{£âW—NÃny¬ABËêpê蟲4ud õk ê“è>– ækóñší¯£¯òf7mžT¢ º]™’)Òp ܵuÃuòÙúåÁñ›·F¶3q7i¥Héê7B^0Û! ‘|tîsÈŽQÇå Î_mcÛÅ'ÁO³÷ÿ ÿÝ?{àN™„õ‘¾rµWWöpÈ@ô8É™Ä Íüä ÜKs8hÚÙøŠÚ©‚A$ Ì5¢Í­D&9nà X¦É›æˆÒdPÁ$bþ#ÒdüõóHäÂV28[O¸Ã0ÒA™bhUáq|I°un1"1ëÖRn~… ȼÔùûH9X­À /_‚Þ‚w”c`0AøÁ•öêŸä€9´-ã$'7âJˆ%ÅMú-nų7çö¥Œ²¨ÚUâÁ! _èf†pÃkÖIápìíÍj ‘Xã®ß¦fy-ÝînÉRþ+ðþºè@vÞ ÉïjGžÒ›F¶øXJ´xmd%ÅdwPþ~õZØÿÄL8Ó–+û×Ù“Clø±Ñ³Í²ÖìjÁ«®Xr«¨Ý™Ò­2tƒS»ãJ€åòýlYÜ䲪'>ûÈdëñÇŠˆûô·òèÚVà|þ$ wâ1—Oæå¯³ØT 1ØšO#0†1ä" –âõíéÕÆ qõÝ/Y0¡Î€-4tÂ.xýa—ĥŕlkU)¨à²n’Â…Ksêý܈’H¼î1¶2EI_,\,Ø0HûœååW>´÷͹ºP¦Å\}°Äú«·¼á¶†µ|îšÕíß lOD¸ð>¸68‘3©È +C:3&exWá3ÌZ|塯jù¨©uôñ³±¹†\ÐL ÒJ°†BþjäaÆ/êÒ%Ñà§? #âƒsÔ½ð{1¨r?:à†ï—"ÂrŸb„°„'9û«£ˆùéQÐqÍyNR1X+¢dsÅkkcvvt’!ù…vTNÁ1%:VµB"jÞî*Ë®äùUˆèªÿ`Ü "“?kOoÊB‹ëB–§órá Ý(.J¡ÚCÉÆ€¦üóAÛ?[í7e]‚›B˰_ì>;¥´™­°"ûÅ¥öTêºzÛ´F´áO¾w½Ö‰m-ºÌ{T"¤YIû0Å0¶RQ\­Ö»…TüoÉ÷·*•8¸ù\¼f.›úN0}¤:àSöùq e±ID²g’0}Oî°Æ×ÜÀpý¾4 Æ1¡¤/i†(EþCóõÇÝQš: šŸ×AöçNŒÂb|ô©÷110y0Æý•€‰îÅé;ÇU³´æ"£'?Z†é–oÈÝÐ ,ìq °’:߿ܵ©ªØ¶g^«õÊØ²Zîݰ¥ú' ¿y%²yö2MÙîàdÅ%_?¯®¾H2'Ô_d?7*-Òæ‡Š&Ì­KÁ¨ˆÉÂÇŸÑ_I)JoA†[ÿ`ÍZìœjs­|Ì^<÷T-Îà³æµÀò3§yË̓,Žtw|ÃÁätŠè{.›&‰p,„eÔ4×gK&Óø 81þU’³>›ÑltwñÖ^¼¾Ô5… L‘ÅÁ¡6ï<¿ ‚ÈS€°»±kH¢À3|+Ë›ËÃ_aót*´ÇÕßÝÚd¥CÆŠ)|bÃ¥Ø ³ý»Í&È&ÖF®¬¥LIé›-0,Ø_áçj×ô<óÕºuÛÊi\”yÞSÒ7âã›ô¯ §Òµ·™žÒÎÖ2jÜúV¥ ˜º[¿êŽEÎóFµ7ëªäZŽ“üŽ©÷tœÕ#IÔ¼4’íŽKýN!ePKÀ²Ðds€GƵœÂNÃ0‚@˜Î‘ÃD‰)˜:-U‡ZC‘e/g4²u‰£g¸J_Pì/ ¼¯*5 –:ÇÇ62Ñ•l,÷T¶ÔZ{‹Ó)Ä6ÏbyLÈ›fL*6©Ó¥='Í–.šì£Owõ°x• ³·™o/„%ÕÔiL»Àà±ôd+Qd.H0=‰ü-L ¨âã—c‰“ÜÊÈDd¾Lð? TqÇ0åÁ|p²8’o4;9 Ç3¤Ñ;@ýM+£¢7¿’Œ- “_ÝÉlß\5‰žnzL›¶ìÓJøF"ÆnŽŸŠk}ºôTÒ?÷ Êžp,VŠêU1zc¶þŽÄÏÑ£R53•\ÅWKÙHq[_›ºY=p<>NîB[+;××Xw°¥8è$￯v­rzýÛ3”Ò“æ<…ޤ &J¡Mw&¼Þ»%ÿ5½À”Ͻ×à—ë&³(x×6UÛt‚9lêü7çÊÞ^¨ä»KU”:Æa¸BPPDʘòý¥€ªm0k¨|ýtS`úªÁþ¥l.B‚AÇÖ ÉÛÅ/l½ÚVéA AÝI“Y¼ygø^hÎbß;Dˆx÷¤çiR®}Áß æk ÖÄ]zŠúZc99æm^ìϲe7}]‚Cbþ‡¨¢rÏɵ^ê~™ë—k¦1Kä¶·bmêrŒWïˆ]QûÜ©üƒöŠ™ 67 5b8^(ÒOOßn KYyŒ'.MˆÛM„ûSÂ"Ôgí8a‰€Y»‘”¦¬ =DÇïåAÄ~“¾ */ú£„O2Mw6‚݆È;0ŒAÇþïˆ?öë1¹6yqë™C¯Nœæ\@1ñý`RÞz¾ßC;R•Mÿ›\渘mGZÜ%gÜÓË ÒÅSÛ—ñ’rúZƃ\“ΫNh׫ÃîØŸhExÞ¿úŸ ß„ì–ÉTu´{ŒHÜy=˜ô0” U ¾wˆQ°´ü¡*nt]ÒÞ4œÖ%ÍôåôµžÒ’¨a65÷ª=BùéŽÀ÷“êÑ.N–DBvX ½¤ƒäj¢;»4I¥?ˆ«‰ìƒÔÓIWàâ$^]OÅÃ6D#, 9‚ ?cšX?PIXðG¶MË:‘¥S•"}”¤AIµW“=©šÌÚ†WyUڵ˽Ðñ$O¡Õo•_˜ªCWÊðJÊe®Å°£DKºOçcFor´fƒtÖß–ý£Î|aîÐϘ$gƒ'…F#S1Ì[vEF:å‹ÄØÕ„>šYbmI'(Íȯ³ÁÂ=ë[]{„Ð5æ‹h\Úí¤ùæ´ˆsÆí;Ëèiem.…tnÅy´G™¯¯Œ`jEOÃôMïV죛0p^PAñ•±W¶¶‹íåðʘÒü&¯µb‰±p?Ȇþ{&ÔËÝ·q\¢<i’[a•0ªÒÀFNë»Ú_‘æµL/ëÖŠæ‡x¹Ô¶ú!ˆN‚¼Q‡ì?ŽirR„ŽÙVÁë³½}&šÀÜW³ZvwVÀœ騾–~ õ½ËCuÒ­Äë²\7È{1zݔš†›k<0m›+"Ólô?Û4óÚ\•ZyɯK×}(k¶Q´5•‰õÄòfƒ·T˜ÓH︽ y5y䔿ãRÖ! =GëÔEûw9UøÓm8ö|­çµýÍÛqnÂJÌü@…mQ¥YsŽ…Æœü~ZtJ®ëñÀnXˆv<ð}ç—¼Ük*zŸ:#UA6ÏbóÒj= Ãàq’?“§¡"ÄÆÞk s9lªO£3Ùi™ÀÉ4ØBùt?TD¨v¶Þ4á?Ûâ1·Ž^Xmó¡©½¡<«›$ÔíLrn™\uù¼f: gH¥Ó<3]­ß‹5ðR6«·Dj)€}õeãoõxËrBœeRý‰!#ÊÐÿX[4(2ˤ.Y|â viíA°~_âל©o!Q>¢·n‘쟮o âh˜©“˜%HóVo¸QÿY©+&~\±eR™¸î!HºŽjêtÖ.™gw¨kØ”ªþ᧪!-/pIC.IzRN0t_]Îô‡Ø8å p –#Pe!¬”¢‚úd”‘™‡oÒÎAVWyn~N­®#÷“u§®„äœî0ú J&nˆX Gèã5 ¶J¦˜`6M{î;¼¾6’¬ íÇKKÎ+ޤ©ƒM5¼ŸvÃñ^„ÕºÙØWëÜž§à1Ž)W™ùqåú'Àd“älÆ'ñ3½brwN^U:ë4UASš|õz¬GFè¿ð¯Uuz¯Ýо* ßÔîQûØ—RúûŒb.ps’E!˜6J]ì­Å´ÿd`½’i~BÅkˆŸŸ3ŰF1QÀŽy*†lFó³iB11t¬F»ÝuöÄÁ«ÄÍ6¡“£ò7áËáçÝ7‡?‰˜µú&y¬*þ~Ö_w9GùyÓq¶^BzP÷R©Î¨1D¶ú¦À†ú:ؘ–¥€pŽÚÊ왎ö@öK^šž~œøÒV2ˆM]=7aP4É£“ X×±þ€h54BjÊ`ñBy‰hEø¤ØK)D†‡îB/GѪÅèˆÇnŒ§ƒgôñšÅP.®.;f@¾þ½%’€ céž â´Ý 4Í»kâIê,°“Ä”kiyòOö9cnAÆHÀ£"ÚúœÝ>_2{ÆØöµý9Bpœ½ddе×8ÄüžÀk“™õÈêªÆÝìÿ ¨Àή܅Ÿæð÷ïŽÌÊSÐÜc„9A¬ÂÁ¦We <ûS {…ÛïáÍSRß* BLÜ€‡«ýk×=Z»Y‡mò«C”ÄÙj2RúÐâÁÖ›f}ÐÏ€Æõ·ÕAÐN-m<»Q1-ªÕTÒa¢ìЖk‘^Ø»àŒÑ Ûظ!p,ñÜc«÷R‚Éëóóå?$Q=uýaøƒé¶±RsV¨³ñÇ»P·Ì í+ÛtçéÀ.èÈß`L ¥JþÛ%8£öj/»Õþ‘‘¢UÓ ¿OmDát%}Y> ßy°#èý=”ɪÌûð1HֈϢ³Jþ£ê²ƒ8PWõtZ™i£ÇÛ05¾¶€VH°—©îc+9þø`—kP!à$íwO²Þؤ™´ÜÓê?„n)[´âk!Éñ ·ÀV©]6¥p¢§®ûåEŸØQ¾¯ˆnbi~/…¡wiþÓ„+wÿÖO;„nò¥/BÆ=¬ÂVݽü Åìí„=JürI‹¸Dùçñ„0ÁW/Ñà’I¿B].µŠ&“ÏlT;îþÄÐú,gÑ»¼Õàãf–8œ7õ&L†ö'x­½¶„¡àŸ¶ÔMf™ì?&U¬ö3JÄ^£¤bíñ?¸¸Z¤Ÿi‹-a¤çówVyNÔÑ Àh„Š¢ÞÔ—áÁ½Ç—“4f5ÁSÀg‚ 4;Ý72¿¯g_5PN¥Íq_!—{Â[P=.$™€"˜W°Ú l£ÄPº5Ùö ô¦#g·ÿ–æÆ(–¬Y<±"ÄÿëOä!B íDû8…-ÂkEçF²€¦„¦2<½ße‘˜¦à+x¡ÁŸIšÖÈÚ ‹6™ÊL¸°Ô Àh=ÄO¼iQAdi¯½HFá+l¼ßÍo ôœ¼æô•£ÿìƒWûŽ=œ"ô KÞ–»IðÏ‘~ÐÆ¸È¬÷œ‹Ü¨õúÙ7[šÄ–L‰ L“ Â«qîè€çéÆ£Æ ¿§ <Õ$€G?•|eOg74®.§±,3Ì{l¹®‹ŸÉ3Þ©E2«•Ìá½7à’XÇϼø’Êr¬ßÆ<…T¶*€žH·Ø‹¼ÎÙ(|2­.u\ÅýJ ëãJéS”TUkáìï-3Y§ ™Ü…”М–wY~oõ.›…ªc/wFæ ª”b v>8_Æ^Á Åù;ñ}Ŭža“ôepæfGÿ†L¼OžÝ Ö[™Š®T²¼7˜o"Ô“‡’fštL©'™ô´p,Ýܲúo>ãöó%êK5•›s«“6û²94œFJŠðé Ò[AkÅG7Zùå‰úÑÓÇ"åW›}¬Ö…–: gÊi"yÝÜ©Ì#ò¹* A~A,k V£`ry§#1òɸ[Ø=¸—(P‘j3¥°ÒJ©±ñï%ËãÁè‚GÉë–ñ¿TŠ6§Zý˜‰ -ídV¿œµ8ù‘ïîÆáðv¹ Y™V> ~rñ“)#R×*®ÚFecËí5jRŸŸUf,^­`êÕˆ>¨bO)×¥¡¡têöºâØ3‘ÏOÄø©.•$>ÖF]Ë]e´Y6©j#{óiTF¸Ëåu:¶žòj°°ÿèôøÈZ¬v&:±3¥RMÕ<Ô»çx‡1­ýc¬Fn¶ šìȹã†ÔS·Ê°N}TyÐÖ¶#ÝŽ®ñ‚á.®fýKŸÐè 9úhO´,çÍÛ5K¶-aéŒÄý6 …û¦Ë|·8Q¾PRjÙdšã²®çÓp¤¹«Ÿ-÷ÍNê°Ëœ´\–hõ£Gñ{mèàŽŽ“ŸKá©NŠêE'ŽN·ãU« èBÜ¥9©Yöc¥ÙtÉâ/OJx8æoe) ²M¡o·B›¼ó®jšÏÇ 0Õ«ÅššôäŒéL¾ê¨iï0I0f½§l3üÍÐPç ‚†Ó?ͬ²µ´˜ÂI<ö'vkªDKõ…ŽšY kß 3iÓ:WeÑ«Ã_܈Ö;úÞ8¿fts¥]Œ*dDÐÆ‘·2ñ.ˆÏô;£5ÑLFhr¸bp#²ÀІÔí*7gÀÏR—(êÌ8b¡ƒB1½»*àͧRq^ Úô)ª«ù~ûX½³85ü—YD§xÛ^gbfŽŸ% à*†>Q”ÌÍ+‰2¬¢ 0ü!LžµûðD€º=5 V/:q†ÆÇõ]Ìå±ëŽ /A*Ø)r¡w1¼ÂÁÞz Ï£ñlN#Òƒ T~ƒSL¾Vò›ãqO3qW=1ÐI¯ž% ‹ð¤ƒÜëów…i¹Õ¨ ¬Ñ*;ƦãAÄ(VÃ|s–®MÃ^P#w+Yôc`áä©€Z”Ñ£!:Éެ¾x$ïÎk׋%Ã}T™ð|ÅPQ ´ÓÏrç€þµŠÝ×»­ÉÛØŠÍ&Z/»ÀÔ÷f£(Lg"´¦Lá¨ðo_Ž^ ª_DË)k{ 2õŸcìe>K1!LÒ_Ì~w8Ä`².Ù÷9²žëÕõòé±Rû™yÆMpo¡xœãtæsÀ«Ü‡MhÈÙ(ü—Üý*IÏï,Y#j±ü¨«@ÇO¿=ó[ß;e' d8A‘­`T 2Ja+Vê£-¢þC>>_ƒŒ-û“­Y’%wrL2<åuýà~fŽàÝrú¶1Ú(ßðVêõ?ã,Õ’QHr#•üx$2Y_½+¡æ^©™\]·¯˜$:ñ#f&Ö)´†¥ÔôÃ<à"Htd”À{¯¾:µ°”Ž\ø \ò;r‰ŒkV®Ec{ë¶çÚþþ§]â|‹BEž’oeåG-´ÚO ´ùå×ñ&ò˱£;é¦ëûŸ‘«fÓãÒ›û“óÇŸÏϺqs}F´€Ak[ À…%÷ñ%^zj6רÖùÇèš3hár9]‚÷!äwƒÕ 3ˆ,‹l•Ý„WÁ¶‚í÷À?Œ@U†ŽV¥:ܪ#„¤+¤êé«*´ äå'ÍÍyá9e™Â6(¤­ûÖ®‰uÊûB+L¡éJ'lí-u ¤E*_Dxûª™øÂõo7q‰WÔrLÑÊì£$ÇB×°ÀÕ¸ -IÈVbÙ,tø‡[öŽ›Ö*Ço¾Å¢š r¹«éÞJzåëy¯¶Z^wJÔ4e’"ÕŒG/òæ¥m?›µJ§? Ì'¹ø÷­ê¡ëR°§ä"¿Ï?Sxô틞*T7 V¡=ÎRûäf¸U\t/Dî@¼/’ÅGÞV´éWƒ¿¹Egl›šTµ¤© o1'°¸Ì¸ ¬™~p˜:$ÿž¯ Z[È>©ë¼RÚ"³"›®yˆÌP*>Q:;6cSöÆJŽ.\¶ñ-ÓS?l_|Ðrõ½Ï^M}ð°ä%³ý±vˆñB!«ZÄhg¦øøFÓ…ø<×;÷©hþØ $^tÿU | º·Újj†¥ÉØë_8FÛžÜf!wQã#ÃÀ$v% )ôˆfï€62‰®k¨?Ñ"„¿qû˜çsGE]£ž®.ðÆOûø]j›¾êFc$]¥9ÐC‘Ò‹#0’tcéòw¸Â˜É?Æ{‰» øKßÞÚåõœºO¦¹&Ù×Ðd휋¸‚Ù²`+½½5ÏX0ÓœHûGîPAØ7¶?5oû-HçýÅ*Œ•²U]ýèp[§Ë%‰Ñ ÏŸÆÓOȧQ ÷3‹&{g ö„rò0x"ÓÆ;CàÕ¨}ÔØàjøkfø½âr•új;Áƒ,³ãŒŒ²~Ê>åXƒàøûD\݉¬Éèó̳=O ÉH™Vÿ†›°§üaùª¨¾¯zÏ:UÏ!|¿K÷=köÚZ]öç/Y½µë¦³ÏSJW]™å  €•ð S¨;AR³E÷H¶(á‘5b LNW¯1UÁ²ô ì]?Ÿ!½9­  ü#ùmî¾ZW#A…æ|±Ýa¸§Ñ¸‚Ãòú…7ϯl«êf^´Ý.…úøû2=DRS$ ê˜:-áÏfý“oT‘|–ŠÕ^Ñž=‰ÐOë–|¡@¢8  y€(ƒÃ¸w“váS4]ËÚ_å;Ó l`¡…ÿnÒlS, &®™T»*ÂÝ#ZÑÖ°$Œõ‹ª´ÅMAyZÍO+ZvªhóE÷3æqñÒ>âÊ“î9è%Mo¯,,Èô†Æ¼Ï1­Þ­l·1â Øžµ$Réç ãJÿ“¾ï.§}œk“‚©ÀTä RŠëòþºu'ÍíJõQj!ËNäÐg’Ÿ·†¢§Ì œ5…°3J8`\`0»úòÑÄœ$Uýî÷“Ûpz¬Œ¡E%Näw˜`4XøE¡4ÍpE„:LÝG9q Ü…¯§×—JÕ¢ 2¨DNÖÕ£ 7J Ö[ïyÕ¿jÃ…€òµe¾ùr¤+ûà Âö#5f ÇZ˜ªÅÜ5RØ, ,ô†ˆzö3-•×^ðV7)ÈýYwc:”÷z¸ÒœUßD¿1W›C|ÿÕ“<Ø5aÂóõE¤ŠÞ~qW?iø¨€åŒ/ÿý®êmFuÓ:£®n½AlÁ¬Æ]•ýÈÌ…ÅéSXŒ9®y=šüʽþ&Oæià/"kÒR_&Má(%ÃzÕD#¨ƒD]F㯸?70ÔŸÄ„‰TI“ÙCƼã¢ËÑy"(Çh3HL’ãìêl¨"rb™ÑwѼõ=ŒõOÛW<³5`N&mvòq¦;JŸŽžBšPG!"1²¯õs´çÈæü JâNzßN~+2²Q»stU],lr[:qPˆ®{eËõø&;S ú±‹-¯ ?XÕ«[;*ª´mYÛå¿©fzùèF~…h&®úƒø+üº¿ÿß›§ÉÛ‘ /X6ûHè8Áœx("CXb` 5¶eýìF°Í> endobj 31 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡GÎt‘øˆ’®>R4éuw¿¿Ï·õ?ÓåøoÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·ÊãésM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§mܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒßè·RŸ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßátF8#ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;ÑÈDt8. Pi|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-AÍÄNèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8eÁM‹³<—“#artË„F{ÇN‡® tÛáÞ®Lˆvqè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿdØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 32 0 obj <> endobj 33 0 obj <> stream xœœ·std_·³Ó±U±mvlۮضm'Û¶mtÔ±tl'¯ß}ß»÷¯7jŒ:gϹÖÜkÏ3ëŒQdD Êt‚&vF@1;[g:&zFn€œ…‘‹“²¡­ ÐÌEÒÙÐð—`‡##S±p¶þŸpdj@G' ;[îÿ®v:ÿD ÿ¶¨˜»]Ìf+7 7#€™‘‘ã¿ í¹¦ŽvFpdÂvöŽfæÎÜ€Ý(U•Ô©hhhÿaâââyü7:Y˜ÙÈÿMà/ê ´¶³·Ú:ó„ÿÂÖÖÆ3k{s'€¡‰ Ðä 5Ck @ÌÂÚÂÞÞÎ@)Lõï*e¢ûûÅGÚÿé?ÿ1MÌÎÑ øgaä`fPš;;Ûs30˜þ¥Lÿ¡èLémÎ 5ÉDmM„ílþ™Æ îŸf G ñßÃ{0ü_®[ÙÚ¹ÙzýŸ”©…­É?[L\ìTm-\€’"ÿÕð‚ûÌ è `cdfäbä@wcs†¶Vñ°þÉôlhkâãeog05´vúX˜ÿ^༜ ]gG ×ÿ›ø÷ÀÄÂØ`4³°…ûõ¿0Ðô?ײ†ÎŽîmFú¿^ÿùüëN÷oLìl­=þ§\ÎÐø?þ¯!!;w€'€Ž™“ÀÄÄÂàâàøü»Ü¿ŒøoþU0´ø¯!ÿGRÒÖÔÀõŸgùkâÀàúŸÑPþm*À¿éÿÒÎÙÂø75ÿʦ#ãßXþ½0ýŸ™ý7þ_ÉýÿÖ´„ÿQúŸ”þ¯ Å\¬­ÿÃQÊÿtð×R'€ àS­ ÿkaü¿Û m,¬=þÆÿU©üÏ_é þ/þ?7´5³蘘ÿ µp³pš(X8›ÿgîþ‹Pµ5:Z[Øìœ,þy‡ümbcúÿ’*æÆV¶@'§¿Oö?8 ­É¿oÌ jklgbakPvþpCG“ÿÐÆ.ŽŽ½þÇý·÷¿×¦§ÝÆpv¬!ü…h;`aƒUŒé`ÂêqÑ'•V-\ý¸n)Žð$•öÓ ˆÊvÑ×Ò­åœk‚âg¥45¯$‰ÝʧCØ+æ½é~”|f¼»×¨’ûë“E.#„ªYFXâ¸.ßÈ¥Þ§¸ilé'P.ٽ׬”íœý'QÂ*TÀæì${íѿˤ“Ú3¥Ê”ý89´µô"/ÿ‘²¹ÚöŒ¬4yÉ‹“Ÿ/`¢sý°Íg‘>@šMs¥ˆˆ–[¯Ž.]GÔ÷3#€Å[ŠÞBKhO.Ï'9H¾×ŸÐ—¼L—áì×û~…_V4ã@Ãn²“§-¶Ãá¥9ÁWñ;Nóseh0XûЉËÏ™ä^h­ ˆp¬Ÿˆž¸Û/å ÖgþßhA…„'hù =u° Q»Â†~äzèe¹ÅÌ …ïX¿®ÉÀ (P%›Ÿ>ðæøúíâûqÝân jEUº’É”lθÈzO•GRܦ^§Þúz’¸M‘Ä6pNÖ;aäºrXàÜg*ÇÁKèÙuÊZ…DQ‹¸Ó~èØwâ?Œä­¯X4é„™²6‹ojSFºâ_o"•‚zòUíô þüiÙl‡ÎD––È•°‡Ñ¶‹§9± Áû­j­}"azL–ºc8ïí8˜©uáQì+hWçðõf2Äk²BÿµÆÁyÜõ†¼FÀGÒöTÄ»ì*üBd*¿‘?™þ—#E±½cØ™=Ʀëïmõ¾öI´¢röÄôyÅ_ßË·Qo†Í) |¦oÍBªòÉ­{’»´†DIÿJ%#£ûYoÛR¡æ^p)!µ»Î¯$õY´ÊgÚA}»uR›ãÞ[¬@¥BH¥‡\…ÎDø…夼⽌ó§O¸¼n‡eÐz•ž†B4‘ÓG×ð–€-ùä¬m¿:¹K¯ÃZ0>Ðx²nšËº*QC¼ QoÛ$wôKNjÝšé³«Õ R™V=?¬\ÅÚ‘~ l‹æúsüQÞd$XiÞÎgø*ï²ÉÎ;X¹¾”Á­äl…®_äò,{¦eWžSpºy,¼ Öþ£s¼§KÒâÝÿ[;¾ºˆ¼}.0Õ[ñþ|3ÿ{€–A'ׯ÷ø2%ü]^RF9C79GmÑk¨›h®*ȪñÖøâ¶3®`>†-1ã¾S“íÈRéJê´&±$¿Mr¤Z ö1.;­¢I]:rÔ…þBä B@öøº\#`2` ¥¤/Ò–‡ƒÏçMƒ¯Ü÷ W€ì96³{¿¡§Àµã­A±¦ôŒd´vüª~°¨ ¥)ÙÆgYåP¯ ˜1dû²®Q›Ì|ü¹öG«îÝ•|”Ü|*Áp…ŒûL›[Þç kçæ«JP‹²O*˜aƒ›7B× üÔü$õ‡|!C ˜©7úW[cØñHÌp>)Õ`·$s€=áÉ1i³ÁŽÙÁ&á¤#1ùšýŽ€9*´ô\á ºÉ’°§üеî4ÍS{—†ÌÅ"·)ûX+_XÖM¦FËcLÇ·FÊΖÿJ«øÍy‚Ô…<þF<ŠàÿB m´=¯IÐhåûé 2Ì‹¸Ê}²fWÄt2OCˆÕ…‰åYÕØ‹Â Úä™.óN9ëîxwL][¸€v‹ùÙ6 €ÆEÐKæËùJ‚tµ”`@”Î5FjvÓW‡¶×¢­ÃÂÖ´½°òéùÞãfZ¼WIBóÈ·ºµåÉÿ[y|¨{önçOÿk|ÌîÅös¦Q’?%Nù/éRÔß¡G<õ]W Î&l{1Ž©LÍoþWĵê1è²é|hUí„S{ňȠŠ^t…FFbíÞ€c ÅV,Ÿ&P1‚à£d`ê"mµ†¹³Œ³‰žØãX,îiòx4O[MË·ˆ´Ø*„ï ú³ÚyBH…°9¢Ú=êNÐ Ðír$Ÿ¹ Žš¡7ì 鯘×ĆŒ7È4E%8õUmФˆ{¿(r¿Ýné‹\fçƒbÌK‰â˜]Þ£à×ûµÃ©äJu 5WUÓÞÊ.µ©3€SKúz´ì7Ñft–¦CeßÎU!tY±Sß i³«YÆ|ŒãÖ]·âCCTÛYÁ\[5u^­ÞÖKd² Ç‚ ï,Þà†k¹Î~Wv´zT zñ„óFý–F?ŠÌú ”7çÞ<³,jÓFÙ2oÌÚP2+¸Os¼Ë<úC«ÞŒ´éÉiN‘F’OìþÏ¡7p›RT4Çux"O˜éJCÑhkµèè!øñ¸ ®×”á‚c·ðTÙ§CJÑçVé!wø»)fšÚˆi,ªKÅã>ùIàïuißhX¡j›á³Ô¬÷ƒ|ñêD(07®ÁçåArê-XmàÙ% vpO‡±¾5-ñO› Ò¯´ ç[7Žß·2ÎÖ”Ó­cçJ)ßgå Ò¬é¨ÃŨ!=w+è‡eGÆåú1ÍøÊj”‡Áðpúl©`áìþBÓç9Û1Ôa`ãVA¼4¸¯©Œ?t€Q•ö®Æzû“»F²‡+K_Âlïæ¼r– qÂ=|‡gsKYGˆI FÛn?Õ:‹W 㔊¿%+³§2ΚŮ;¨•ÞWÃÃg!õ¢ããÔUñî›Oê=Aç÷bÆ!P÷Õ5ŠtH'•›é•+º$×BU,ñðKm09÷Eœ¶m}'ðZ/qJ94ê­³}%«²–¢[î3_T¾ùöT;ÆÖRï‚ï;á@'!‰3‡›ó«Ö‹ÓjÈhtN#Ýs\A)*ب~A ž‚$+•óήý! †ÅŸ?¸¬¯o¶Y; ÆhÌC¼Ú®Âï¡z΂_b¶4øÐ’ùS ƒn n‰àL‰I>¼h®™h]L[ÚudGÏö)HF›îÚQÙySšbl¸vª&ñ†ËDÜf~ÛDý‰›ÀwÑI }¹xBˆxƒŒUÅ{ºÎ— m2i,LKŠQ,Æhje¡¢Ÿ`êB9Þ˜ žÕâ²L™lá9h=Øú&¤Ë÷Òæqä¥WÊÕõô·RŒªRbÜͲƒxXÚ÷–ƶW½ÙH’â.=zO¹9¿åªFêadmW<-ÒE´G·"ðiÛã«ùÍ»¯e Þ{bu¦zP¸Ò_ Â,ˆ«“¦sa˜Üqr6í¡ÙžëÍ+«©ðT–\8[£Yb5/û9ô»gÊ»8þì_¢á’‹Ô@3šcÉbƺâ͘“¥u[Øpm´îãžVðÅvA¾¡Ù€ OÍ×BÖHŸD lÂý1i{1'¥ÀÍ-zbQýíún@”¼‘¬‘TÑãÈüæþ q.I˜ã£Š ¡¿þÄ}tÿ¾ä(Ã,7÷˧«[áO¿fYõDí{]¸·s|pà¤v^.¢¶qLähK*ªr<#:¡ç w@²_%ÑWÑœwAMcÁÕü‘¢ þü]„£Ç‹S3Íï³;÷½‘§ê8%ãKcGÿy÷eúhÒ„ÐR];,wÚ> xNÓH:WbLà§§0 ½ÏÄņ‚L+ödZÿqî)\¼*èåSnû·8.däzS&iå`æ‚Á7÷˜è–É×|>Ÿú{þëj ç?5ð Íœð½•ãNhóá5#mÉ‚TAâ*,zI¬5#¥ÊÑÙêa§<®z@ZÌ´"‹u`MQdž@«^¯Ck©ëÍ8Ð!²4kE «Û8é&Î; RÓ®ö3ËPAïpk1’ú5Ù?[ïÚÄG|öTP“`ªd/¯f$ЪÎvÙ[®Øan+ÉDóc9";vÅXâ|°5‚CW>%FTv[Nü®bÒ¯A$˜¨ž~·¾À—h(ýwòiʨuC¤¿*FÅ]£¢lKòjN'ûªœRn ÈÈžsØ2ÐgLi#¾©'ž>´ G¾,Þt.ÈâÖ³ÓÜ*oY£ £©ì¸Óaë0ÉÉSwz ÇÎ ^8ɱóyàåº0ÍÛɳDƒø×ïÕ6š·Pngô#Žº£Ã­åD6ýò¨šë†'%ìØ°ëd×ó•ù––ãËóWŶ“)p„Št'#£¾§lÕâ'Ûs™ÌixØÊvþÁ¼c7Æ*sAü9»b²^õ¸æ@—æïÌï*AG-`RêÍ5€ ¹(–M¯¦ç 2ä’§Í=8K>é¬à‡Tbt «~ >›~nʸjàÚ¨ÜÁ§)[.—W3A‚}«’'œ4™„âBHÐMÏmÂ@XÒ{L ýÑå ”¬+!Ò¡‡â3yõëy‹Ãƒ)3 °"€Hº °î¬CÞV$uó±ÍÇÂx¦çÏ<εÙ.\ÕÇ‹‘gl.¦KÑõEÁ$‰šò…ÑM'¹9”¬s¨5–üiN'ž˜ÁÚõr´ÌF¡’EpëºïdO>|z&sºGÉÛÄ¥Õ¼½÷ŸsKç³ÅüyÅ”Ò'æ˜ysy0™½O¦Œ¥LSÇ­íë乫ñ_?P®…=;¶ÔkÑÐ9©—2¦î^"›6é]KÒEœ„F õÔ=®Ðý¹]?šëOµP”ãüšFOÕI Ã[ ZLDÀH¾X²Ä#íåîBôtPDbèÂäŽGÚ‚Y7ÅÀ5·7Ý\b|+×Wãnì‡×ìwW¿y5†Ö„7r/$ì¡YáÈ€}ÕlŸõ¼«o9³Ü:JÉPçqŒ«Éÿ¹õ’vÐp} <>¨!O„À“ÿ~tˆ+«YÆ MޏøeïЀbUù(o§qâomNDyÛ*ôüÃÞ8†G=ŠÊ™m 4!LNèþdT@‘ Ž¡6£Q´¹gKþP狦Âôù×›ÝÉ{þÆh^ó £Ü¶¼ðV¼$IÐ^÷A6åsz÷ËÒ„a†ŠDz<y¶P±Ÿ¯D ùž1¥H-ÍQøÄ¡š=]Z²¹0wÈƒß FŠÄ I¾A—/l93û[ »ßù¬ÚxX¼* ¯Ù¸[[_³äÎwØ:í^µ©Æ@¸·`J¸ç4N¤Ñ%(‰ýT]b 1Pí«¨Ñ,›/PžÐìû[Û©óúLˆ|{Ô¿1`PøW¾ö\á>’¨,¦÷îiïâ³mZ'B×n håƒvX¯—HÀxêÖ™¼Ä{„ØÄ(Nî¾Ë²%u[,‰«H•YË@ÄÓ²h¿têªüÒŠ´uø.ý $ºª~ —¨ƒ;ÁíåÛŽµŽ÷‹îß1gÎ}ŒbxŒ¨¤î›K0—¸|æé+K‘¾F!ó®–ÍF½üðš- }”ã1È\…›c±üó Ž`AË_éö³IæöÇ;¿Æx_AÓÒ·;^C󃸜ð¦}40´Ð!£§¦îH4tKrQº1•ÜùØ6NÇç4]¼Åclø,œÃÉMªM «n3Ò•Ëä¤?eVóŽ‹p‘’Ù&J@­÷ü2ð›Qb¡Ñäè ÌË¥¥AB:¹üÊ÷Qäœ2ܰ½ÂàAB–Ú…öñLðt60øṈ̃,ýÄh_¡žJ”Ò[BÄÅ|1—yED pšÉƒgáü {×EÚùÓsjÜî£SÁÊ#ð"Ú„/yÿw´o¯R]Ÿ÷¿¡L’‰XKÖVúÚ¦Þ¶j~'”ˆ±Ð¸,‚«1}øßW¼£Û°ßÿŒï¡¨Ðš}ì™êêêë“t½EãA—žäŒ–úwR 8}%e{,/•߇“E ?Öý/Æ“{ú ã¹^°gŒãž,S‡ÛçJl€äExõbÛµÝ1x‡ÇYñH~…ªßÞn1•ßåÖžî)YlÄa’Ú芻J½Û‚F¿ûÖö¨Ç>Ú€t‚¤uŒTKÍ/ûùøñÑî¤ü.¯$ò×û‰B‡Š¬¶P»øE"@«oÈìûªUt&0ëSÁÑ›aeü$+ÑNVŠÌ}D™Ÿçkë5M°ûÓÈ-Ñ$ÕÊÓJ‰°lù£­ð 䕽¼éÛ&t Õ^¦§eæ té½ýðÆ&LÛÁˆ‡½6™@×–ÕpÙ¥‘M샦®÷µ×,´BŠÉªo Ë»ÎÖ\ù¢³CTfƒ­Žî÷šÌf™»© 9 0eªyœr¹úÀ¬qV /åNS0šIe/;”%DÙyÎ쟡Ñcû®ÏNð®ç¥}˜Ñå&]C9ÒE0¶FÚÄ“C‹9‰D“ ª÷³ëtl-Ó¬'æ¡êWÄäÍ‚c2ÒæÝàÓüb¯±‹Ò–åÍNÎ Åøâ›c;?M\’)—b¦þ„ˆ…ñ¶I<Õ[ÿü£¬£Ÿ¶7EÑC,Ä {(=Ä×rlg¹2NªÌǃɚClW®RÍë‚ÿérË©…C²€Ìý™[ùÄ‘ >¬Ò%5ÒªªÅæLYei[àÍzí{ýaÉŸî÷¨ÝD¶(ܺ±zxdDfH§‰ï*($_c䌉)ºÈ¿*K²Q…Û—kå÷;ÝfX/_dq•—L<ÂÌÞb.—Æ­f²‹³"ÄùÚ =ræ›û°ái7¼Þ$lMƲ rý=áÄÅÆàõ=*œ@•Çfµ1*¬ÄÆÓÏq‡Ÿ¦ó.N~ri»m#5¬´ügЦ“^r)÷ó¶yb1:ÄxDÑ6¼-ò˜quÓ*bÔ¸I´JÁµOɳ‘+ÊC!bC]÷•&=ÚÞ#ž²9F¬(ø4]¾‹L¬ˆô(¾çSä¬cœÔ\el[Ç–ŽÙìž~j¥€Ém®ôß/£;¥ ’Íç,ÇoÁq`;M^ÖHZ R|,Dè׉1œÝ2nÙYÌÞ×dÃݯD'Ü!FŒÆì˜ßµ"T`Ld­ÌÍ2„•yõE)ª¸ùlj‘ŠÌ!áB5…M^À¨ÃãÃDvE6¯‘\ îÔm»ŒMf4:çwÆñLÑϘtFšÙ¿Ô"}ÒËüñ®º Ó«æ{[1S IwÆQ©)KïŽ Ð[,¿9.7v¹Äœ³‚—êOÉŽŽ=×ÐjΖ²´joBhh›SôÜžÈYzŸG§ø¶2‰¯9Aæëo^§eÆøÆ[L ¹¨‡Q§ù@¬’®/k‡¶ã8ºñ ŠÌ”ȧ•2QtŸqJÂöÞtÆÕfdÞ”×;p™ êHì§ÿ§*Ác›X8¨;H–4'v? s4¥ÈÖ­wm%¦^RèÏãÈfpSPn z°ï|Â7_xéu!Ì6­Û±ùRXF¼ƒfx6 ê®"k`—G¬@¬QhÔº‰Cy‰äÇ^I½ åÖv"ئGêºLB^HàåQGG 0ãa4,9ïô–ÉV-P.‰{½Âé²ï7SöǼKù¹ª[tÇð2N@Ÿð¼êÔåĤ•ÆÁ`Vw,÷rÓ:#„R}”àQ’µ.Æ5þ¸æ›5ˆ¿‰ªG¼îèI|—t@Z§ãWo¡€¼a!¸ŸA’k`9ÞtRɉú<ó…•È0ÁÐÉ+JÈiRŸf·gþíž&9œí×tbRñ¦k¹”„•–IC÷0Ȥý–sû`—¨R‚*ò³K¤XÝL­ÜמFŸº¢,±Åô3ÝRݺ9å½iµ®ËòJ/.w›ÔÔÑ9Jº ã¾ —õs2ûº”ô³OL Á14x!JÅèãKÞ¨[ÙS½‹Ü­³,¨$?Ë-3¢ÍåÝ»åx¾z¹@„ÆÛ3UõŘsÓkûñH".—*¾wj±Öû§­¹žÚ-zƒ*ªk}ÝÈN\ïÁÞŒswjÁËÞÆ£ñdè’@ÿÚ.3À™éA•@àä\¸ãLç¡“ƒ²æjyº Ϻø»@ F B¢| ¤ìñ”±c½~ ä}ý[æ'ÃL²ÿbÂÄÔ U?†î-¾'_Dýd¹ŸðÂàE¸(R’HëÙ œÅ˜i_¾¤ÞX1ºÿ¯k/¶qB Ç7ãйüù´¬å€3[ÃkâÁø0ÊQ¢£ÈgutÍÝ@ÂÖza—¶¬¥ÌØ?¬"¡“F ÜvÒï<\€.’O‹ø®2AØâ¾CÍ>r7†Ÿ]“åUXQ'²‰´i ÈÓ»î]Îè3•tÄãÆ‘ëóÁøASg½,.Ù|öÔ!LxÎnÿÐæAtp®&ë(Ý"lOiÏÀq;’`-8‹=]’»fì(’ÊŒýGw2zg޶vüa¼´ÂUôb²ä¨4evGOð@¾"}¤·pG{=›B1Ž8 ÜÜeÚ †#–­D1ç0ŠÞ{æ\XÏCúó‘ º¸•Õ=‡óËŠ"/TøåijÞåÆb¼º†giBGm`)™[×  Á$JàšþV;°¹Hû€šþÕ6?rôâJþdŒû®¾Ý ÍóÆAŽç®‰¾oÿéÒ:¾æPìýñAŠG¢D>ñ`ÆËXTGp1t)Ç9É{öÄxÇH[AñëÈkN\µ‚É7€ß ýÛ•àͼOóAM®q(—yÖ}ÎÞ@ïDµ¶›_"¦ „÷ð3íë‹„¼i9{– åâÔÔÕ[&k»¼#üK8ÁJ8 •5oj\*ÉÆ¥¸=½™amæÀ=^o6«lE‘›´yYá±°;þ¬ºšÙ×.Ç$õ¼·Jö@ÛIì@€æ)Xzˆ]¢í·¹{6å¥ E›Ò‰š¡ ùü©‡³HÜÔ"èmÅE<ïaÃ|eYÌËaôXZk Ý0aîiàï‚‹a"2þ!šïà—ây-¢L(uizŽhuU{÷ xr¯YVS¿Ú…ÛéÑÓb‰Fƒbª/l_mÆÍs-5lŒ4Á¦ u¸»gÏ]Ýh ¢vŒÙŠÁÀ<üÎ(Ñ êç¬Qëãb ¾»P甿Xt+‰¢€óݦ‘]Xÿï† Ëªa5ë¼fÿA $]O¶Zbzð¿&¿6Ñ^ É?£Û§ øL÷@è@m*Aû±~,¼k6qq<Ñ'Ììµsgüœœ¥çz°{%y¯ê 9E?â?”©õÊûꙵ7ÍeïjÀq~.Fû,_ÓÍÝmžº’‡¥ëÒK!åÖÜBïµ€…w Ø/X³8üýý‚ÎMF¸Ök¨À!]á„5ç<¥òúœ ú{⇌µBîø8l%EĔԌn¿Y˜‘¶@hz€{žm3]Ç$ ¶Ã:½˜ðeBúϲX$ð(=5}U”â£Q?$wäÂï"iéºìæôÁ¯CÌg#u®÷ÓL“9ìû3*ÐøAåûݪ1{$6ŸA>Ñ"Qälú" íYË«­Õ7ˆ7Ù >9f¡Õ¢¨UÁ¶Ük¿_e˜Ï—ñ{ÞÕ ¦›°±l’l‰°äO}£4Zç’pP6Hç(c÷.3æ¯ß^žñåþP,›'©Çç¶¢&ýð õŒ?šÙI¼±δî~lèí‰á,¡ÊQG¡"d\ÌYÓ´€"ÃìˆHøu7¢Ãí”èö³þ—Ö2­oãu¡ øê´W"ʉ1Ô-Šœ%ê+|䙳Ü*'CƒRÏZ9ОíMur¤a_)>Œs£¡$¿•|.Ø=äã0+É‹wì쓈-4vët«nŽè#¬¼€!PdÚL÷ûg˜1Ö2}ß)çãzâv )hײ§c¨Plj «YÉž§×T·ûècÆ»mneøZ'Óm.”¡µóØFþMàKò kíž“o¡O'Uõq9€ìR%CwreÔ½ 7< ém æ~³c£ibMDAoK’žHÄÂ1Ò¶ÎÝžôkTR‰G-è9·bƒ Ù\DmÈsc·óêí=ÌDKt˜Œ ¾Öik—kýöE5…µoOÚÃè[=\ ýS® ºh^õyà SsLè­7‚&6÷¯K¡;$B‘,âÝ_ܪCBG«ñŠÒ«ãƒ{E-ˆ—‘4KC9ztôàé;ÃÖ‹:Ë€˜éYgrWþÔÛ½´M›>:˜Æeò4s#ÔHè8uŠ]õöŠ@2?À0‚‚ ™˜ Õ6U±´·‡³‚Z~s‰¥´“|¨æk \ûI6±ÇþCd˜Nê%vX4ÎvHèýå‰þ5“ûw{z[8Š'±ý˜ƒûõï£I¹ßÍÉ9Ca‰µ?רX½A…”C‘DåÎ(”(¯.@Bl*\äO³/„‡¯$=×»¨–0V'@gµ?¾Ø†¿«Ð¥ìCÓv87,–ïëÙ®ÜÖ7 j¹ˆ«›Gjm÷mê¯<ùBùMÕÒÓqõ<-v»S;ÄÈ]ÈýF’Õ‡qsš¹Ñ&´dX²{&_Öê (êÒ"üÁb3ì‚uB„80B ¦f‡ÆÅ”T®.¨ÏñédÓ] Goç*ˆÎ„ @qÂæÁ•Í5ÿ%^œdoN¬ŠÆ³á®Ñj€D.‘ŽWJ·çÖ®Q+è„ë‘_Fû~z(%QM…½‘ÉfH­<&ù•ßÑèäÌãÇÎ,¤Ÿú‡|Ñ+¹œòèë-õâ|õ5à\ê5Ù_Gë™&ùÍü °úO·"MÞ.b0 riÄ d×I7žÏ¼ÔXºÏU›†E賆U%DáÇî|Všº]):z­ÑÚ¾Y›oV€V—’ê¥@ciN…½û¾ó,#eÚz¿¤¥¹ŒìJœFpÖ*ÞMýíÊ"36I=RãyR#ä¶xÔºãK{¨ôqý°(D‰ nÅ!W¨9½Y²ôc½‹XǯÈù;·G‰†é ׳“á²Æ …JؤÖÉ^eÎË„ßPhé:6-­Ù\Så~1Yíž½¤ÔPõp)íBÙB~è0θz¦çÙ胘‘ëåFBi†à!YðÔãôt{êËæ©)ÈÞö‘6l ü^€÷¨üK´®Ü‰Äˆ³ì¸•%ƒzúý¤€Áˆß”òT¯Lƒ|CÎvœ{{Êá‚ãô•§52Iböé~¨ &¯aüD=åÞ†ÈìĶxn‡",žêsPðãçliÛªd™–iL+‘‡°Ì›m¯V–ö‡Idöì°i Pu–vþçK›Û'‡*Ÿ[ƒ¤I±„ ?ÀU$sí&z;^ìï=i½è³Î¯³nhÓQHt·t«(˜ªÁÁxó»‹Tí/øóǶB\7/¸qÃ&ÉCø[oa r#»>ˆ7=ž®! èRÑoR:§×¦íR¡Gâ'Ÿ¾Ÿö¬ÎK,¯‚ "‰3uò‘ì˜ØÃË™)†hkÊ‹œS¬¯–¾6õ 8•/Ç §¾kAºt% -ǻԲë¥|R« þlºLÆÄÖ„¨3Ï?KD 4¡Ù‚¶Ó{Ü1 Kq2 EGŒ@"¡î,TN‰C¡ÜOa6´Ž‚ðéO—%»èÔ‘äu­6œ}hm'*ð'ÒÄu>º0#?î ·òžÌÿq‰ÐEŸcaÏ ˆ §óæ…CùæaÙ U÷@SdÔ{ÚÚ4OsØë0r5+È¥îf”ú¥r3¾} +Œ¦S¼ÍÛooM«¢‰²à%â±åè# Šé e¯,`Sò;ž-®ÇÀ§§æli®åiß©%Œ§˜æo± FXI<ÓÁÑLàl÷Z‡/GÝ|ëØ°ƒ·ÙQã&aGªšs±–n'!LŠ>f »Fž¢~‡b €ß˜9l ÏÚ÷‡<®ø÷¿/b”»{øS@áôæèuiõ㞘}¨hAáæB-×!+/-–ýèPþ¾­Ëg3¾ûL¥+oBùX·À‡QÔãÝ»îf~mô4¦@”‚¤‹§¦øU³N÷ä9C¯÷Q~ŒXx¸™É‘öI'Dd{RÓŠPÉE]ôœ»y(ŒË {T.4OIÈ$Õ¥ ®èÂÇò_I–mw˜Ä §n;cõý)ŸÛ턆r:ÈÒ3;M–¤H⩸?VƒE¹<UÉJ¦£õáÎçm«¬ûÏôj.€ ¦SÊé:ºß£0wyÀ>e𵸠8§ÙAÒ/a{kDÏÖƒGƒ¬´»á³çÀDþMó»Œä ¬UÄÐz4ÈÄ×2Úø6SqÓm—ö-*¨„ˆñŠÃ»YRÕÒÊLS²—ëúÍÕ‰áÒbTðXk:Ïà…k¥\PDòæ`!‡³:H¾WÅ뢯¤‘o«„CŽ5wÞŠu‚ë‹;¦§!ÆÞnò5T—XÕ„µ™¼%ƒ:=Ûd+Y?P:ÊH€šé«)i¢çúÍKG;T¹Í ƒ’FéSÜÍÌ@7pa¦ÌJ$UºfŠT`WßLÁ™ð•ÒWç5–˜x—(«ÎˆxÎòjZ°j¯æºkSË…z*#ÂÜm¡0f³Æ©a â&e´ 9$‚0&Eړ厔è^Zzé˜òÞbPQÙóF¯¼þ¼4¾¬¿´ž#Ê †¾µÌÆÄ˜UÊRÁè±5xQÈö”+•è¿w“§]îë%%Ó`ÝêãÝ&F7Kd‚.Ì`¨Œ Þàd‡íËÇ ¹f’°(›b‚8HÈè Á[=¢ë;.™J;8v}/½ž=Þ“¡„-óØ;À`xätUyøA°{¢ÈÚ]'™ QÍxl~”Ôãí½º7LÕª;oz)¹){Îpòšµ Ó9çþÃïÆŸÛ39|/‡/ï!&µWÕ’¥nÚ½w"úAà„lÌ +`þr·°ù-úbWhI.ÜÓþ&3ß'®îð  ¯Ý0œ½õQw¬ÚÏa*.n¸.åÂõCèX‰ºw*™WkþÐÚö6ƽ(è'ºPëæÚŽ8{£èI‹û|(c®Ç×Ù¶.ߦ{Æzá  ]ÄòTBm¢…îÒ\ÙÍTD8б%¨…qi…÷úM|h‚cÝ ge£6?}•rQgÄ…˳Üé[ð-c&ä’”OP¢c¿úXü1­ÏB:P´âÊ.|]®ŽÞX×´$¸Ñà–UüG¦©˜Í)siB—€¾ÿ˜bsáC ÄB:çL@àOŽyf•1óìbýê=£LW&åubwÏ¶ïøµ&wþ'™pLjš{¿mÿ€´}pôHçüð9Í:Âaç±Äú~¯9§dYòie¹ÜäÏ>+N:oÖŵÕtOMd[˼:4…Í)µkA£3Íù®vº†½ã­]H 9ð¹•ÕÈìoi£jË áø)¬§UÍX< ^õ“¼hß_ˆSžþ¾´c¿k㸕 3ðÛßš}Ô!Ú»¢ôŒnb²r¿'‹´Øï×òx ÷^”OZr£ly ßC´ë–ÝŠR)†[ ëP£w Ü$®?}º=t#²wózPˆÝßKÃó[2<~%g]´h£„å¯Fã»ÇÃèG7—-¥/ìÑ.›h8{}·}„šã!<)'2õRcX—h%}nþdvQ°öeQÑMëÎÖ)ÌeÆÎ\IàZªõIÍËùéû€çî„F¢Ú¾²rœL‘Wˆ,‡$†~¤ÝûåJ×IJÀy¡I%µïÓwÀ¦u±Ø0) º- mÊÎígºZ]’ãT"al±tuYRSŠƒÒœ ^Ä¥K[À—9"’Q¦Yî"SNÆöƒ«=ˇópzXìžûtXVŠ£áÃr>­¡ÂóGú…ô4Ìé3ƒ$‚¡èªZÑZAÐYó¯­"Åw8AJEžÆ-䧯ƒMÙµ˜pðN•Ð îÿ‚@Q7Eäýwÿ†Êþ²„6KW%LòEíãY !}1Fõƒœì´~¾B¨´7È© _‚$Íæ]-˜å«ô¡.Š,Ëð(Gb·ÁeòYܬ†¾X¶ùå¾tÐ* OJK‚ØÄ£Ÿ)BÉ®#O&?+Ë„ UŠ]È ;?L•\GmÍrz¨¦òû‡úVBØo˜ŠÍ,Aét6¸fEvǧ7–Ä”p&*™³9F J¹½ž¾Ü7x3Â)æøRTW!³‘ òz®ße6YÙ«9V}ý.½¢Duõ޲YÑ×bÉRôg“É¤ÔøÏ{ï•÷ÐØû†Üeƒ“ÔJµæ²‘„3W ~XÀé"#º„EfÊîU¬1¯Ã¤*ÿþ]³S澩1±9w!èë4Gö–{UAêµ9S ‡V”.gdB–íQˆQöi÷€ÇF¢-~ʉ&¢:íÐ=éSýø±Y_9ö3MÍÍî¹Í'Ê—yKæA¿ÉXÁän&´ 6³¦.·F×·þ¯ëK[Ÿñ–ºæÐ£žFá Th¸BtZaÊ(dÉ @"}âSÉ6F¬{ˆtD'ú«ô\fÜn”êŠ_%±¿î¨ÓçôÎ{qéêP·kÎá•”‡ÞaeÒ¼ß L—J¸CЈ,ïÜHQrâY{\Þ±wò¾â;Hx ç-ÙŠ²ë±”¼õbys…*Úñ´¯QIkàF~LP×ÈêÐ:vRˆŠSŸöŸçmÄN=u¯seðVdù4*Ÿ;qÃ^Jý ÷¹)S¦Q„qÈí-@ñËzía—8«y·7¢ýF›/;21©*xA=d ¹éØG§Ô•“¯*%ó™,¦¡§’¤-”cµ¼VÓqÃ3GÌh0f#xÕEè«Í8L­7—ærƒPÍñ‹/·ø¶=ŸIÿ¢Á,šŸµ µó.šÎù­§yh«UþovzÞ›¡Í.ÕçÀSàúIqEß ðí«I$vÂÕ$ØN_öBy¥ù€Ì~4¥Ã™í,Þ–é~ÂU`äycéQ8½Ÿhdû¶__ãC¬Íu¹Ž˜2ÁçY/›a}§ÃÎþòÓKMjdvÀxßdË´»HéñÞVQª±Â,§g‹VÚ[O]Ë¿mzJ²·ús‹àQúæ¨Îv“$ÕrS7”¹Sî41+ë2phÙËõÊùvªX"¬s\‡~´â…ˆOôBЗ6Á˜LQÜôÄË`ÖСûN^»ïZÛäç¢aÁkù0bôdNÍ^z¸"ns²‡ÖÝÂŰW¶; ;íißcÊ51JgSKßà‚:Έ'«z¬HÉ5‡ÐùDõbD +äaÚ‡ÍC^uA´ìOŸ—™àNè6 BþûÐÆA–/sœxgceòÊ´°¿¼ŽÈ@Bg}ÑÅCsꦊRázìÒBYUCs€dE²VÇh !¨„Z1íÌ9\úJð”´ ¹ÇwŒù‘ݧžÚÕ‹ŒZ›hH<åªC $¦Ds]£Î»–ß ÂÙÙmÁÓH¡°¹öÁƒÎQ5Sì*Àá ­× á¦/²è)©Ã# ö·zd{x‚ߊ7Ã@îÏ®¹c\­jR8ëò¾ª¾{w»zx_ÚÝý•ð‰lu«WqÅn³¯Oê-œ×i‰¾•ÂzÃú­U²ÇËQ½‡Ä¹\ôõŠ0·`cÉW^@·‘Ÿñ¨¼0jÚi2 žçâi7iqpA3ð8zb㎢š™64T¾T*Pš-þüJç9´Ÿáò…rIDjK¾ŽÀ>ã õ • ÙÎ5{Kw.Ÿc‚ò‹è«NПhŸ ˆ‹œÑC£‘!Œ„©ò-ŒVÙ€ñ."N5ñl65l¢îuf{5’iuJsfKã*«n[Ò»lµ€8KÒs½‚ám¦¸#× Nß•® M$Â4 Ò¸oó¹Ágœw·˜Î)T°ûãZ³[PÍÄÕBË€‰ðèTÏ@ŽòiX e’¦!~@—‚ ½î•wŸÁ*ï,TJ­… #â÷UÊ=B•/°•íþ\Èà+Õ«KÌk,kŽò p:xÜ?î<³Æ"? é-Pۺ̀ÃA=G_ìÒS$þ[L•^´¢ñiìý3JÑ{|Ú›¨þÞ­‘å:w›hà"Ú~MH  ¤9ÓO60$CH5V`Ä2r©é¥:“„ Šê|@œ_¼W¡ÌÍÍgc8¤xòúAãÇ?ýú«Ó! ´¹M¼F™B’°vÎÇÍÓŒ¡Â…hS©l)Ry9jîk³ñ‡\Æî¸,`гîÖAÜtŸì¡ÉÅ•‡<$“›Ì1 ï€"Ž~!Ók.ä´Ë˜„ˆ@:Á¨ ˜Ö-RÍ0z1ˆbhÜf½ðz§…2*ü6Ÿ!—øþ,O~,ÄFfúŦÒ{çwÆÊlý.×> ¾O²×'V«;K<dÆK3qNFʙɤäó’?þ…¯ü¦vŽ«c$Ì{Ïîè î7AÝôMYå묌X¡¸TGÄkÑ”ïþ¶x’±fY]‘±-Ôcä]¾'~ ¾h?aSâƒrê÷‡VP`,+×ȃmÐTp8ÒeŠç¾ƒ«È–•#ÔIVUÐGäçU‡J–YKFÒQ³Ñ\mG —ŠŒîeB«söaøÁ6äáóÝ¡Dý1þìÅøÞÓ·Y¹µ Ī’bî­Ÿ_–ÔïK {LàaNyЋ¸²›l?/#·ên{¤#È?.vÄL¤L”Ϋ¹(m²²rJØ0*LiŒÀUbTùb—œêP¦uó¯3:èpÇ:q#ƒ+®ûé›-,¹Üååè näYK~ák!£˜»7µ „‘̽œ#$bXÇ»š[¦Ähü1± ½c Ç s¹eˆèÒG…û­ôHÊ*Ï m™ÕÍ uî‹.‚“«$ÓþŽÂù º©°‘J¢ÑU(¡\XZãÛf&[Mñ4"™^Eu†wnß3Œûš€tsö¦çE+ó`}¢~58îÿÒR±Ñ¶N5¹…{¤×Ùšÿ¹¼•ð ìRbk9?‘Ð"7ÔÛä$³9Kj*(¤M^È7úèx06ôå³e`Fféϲ€mDà4—(S ꉾ0YœÉòU÷ááYL=\›â\öúÄêsX)® <…]«wvaìýÓ&PU®…x~Pãæòƒ2M¦O/Ï¿¸¯Ö¹;ã»­[xùcÛgbDðoYÛØÝÞ=¬Î¢$Ò ¡ÊCC<®s„ÓŠŒ/¬trJq+f»1ĕ L=,YnxçÄ–ÖÁ4u¬îqùwKšŸò$úñ*áob…µ‘Ú¹4ÈËÊH]ÌqQ™G ¸MݺSuŠy;oïÒXì{U©wÑm6˜SB¬%60%Ýݯ²)Øy³°Ã{®.}fŽ+M½žê¢Ø3¹aD½ï÷âdÙ^÷¾’ÙØu_$HÛòdb® ðå8áÄù{ãÀºN ˜ú=¹c¢QHûÖZ~!d߸°…üTÒ/Ó_Óz#jRÜBú>re™3Îè-)¦uþ8®~Õ?u­7¸4Ú…:’Ý1g4å·õå¼fg¢«µöLen¸³„g-[o&IIžcüºRÜ™‡b‡­à”RŸOÞõ êuXæýÔVÓWºƒCDdàH‚Êno3YàJ» Ý?}Å@Cð™ä ÀŠ  îKm ¶¤l°'¬ºòžK\Õ|,úž ¨šÒø Gôâ7MègØnü^Êbsß<ë@d¡gâýü\G0g^ºæn_© ¥_òšes|lÿdȾ¦º•ÏbÖ8âTH4Ofµh´S:Y¡iq~£Z¤;ÃiT/[x ­c|MuýšIp·Ã)‘-¡Ï‡ j±»Æ^e&p UMê»ޏ󼏂Ò%ótMIeÈÐU9:΀€Óã¥ö‹†Ø"ãÇ®LÏŠÔ»òKU숗=åÄO’0¤f„mÿ8ç}ÊÍ:ÇØ ZâºÑݤƒ +æ=OˆUO&Í!ä‹úÀ€N¹¬Ð>ùf6Ú'«j¡lcŽª¿Â4ÍRý™Ì¾‚ŠúèFyÎ°ÕæžwÅ‹ÖR<_A¿‡ßÿ“S·Å÷D‚dt•u…sd}e·Â%ZÔYº|÷½r«t8Œì¹ÿAõ<ÆÎþ~ƒÂóyºo;•ƒ:ø€Ñ¹j¦ð¥° B¼&|×’ÔÜhʆ”³8¦ƒãÂÜ›008®—%íÕŒ$òkf×Þ ®îî ´ûB®Yå¢aMô†-­ð óƒ®Ò‡K«L„)íÙØC’žÐI :x\,õÈÉ ˜UuìpqÇ"P‚ OœÔdÉ`ÛòÊš&g*ÕÆW”ÜÃûg’òhÓl;”B@èŸ8þÏÎ3”³p·;~*«V¦ëÅzêŒ#³‰¨œ¬™Ðôš“Ã[o¦ƒX ÏwÕc˜CÐ*}!˜Íeû6#›Vröås{7OñAÄ ÷}7IµoÈJ»q›X\± ßÞ@½¯DíKO÷myó<_…2 ƒ?O²Š}•èAdÃÔÊ]êÈâAÉãÈ…£ÜZwXëÃ7+¶_c1¦ˆ'|ù"œŒ^ì NlQ¬<Ë;mïFàXœÔ{Ï@¥·UfxÙM’4Ön8Â2=÷v€ÕKIãâïÈ¥â¼R·Ôé{M“¢ TFpìÍ·Æþà©ø)–œbÏ ˜k^2p'a8“|ô€»þÍÁzæ˜äm‡˜?ÐV=¢…*Cæ^èLu$%m±Ë~ë‡ÎÒ)tŸ®´wMÔ´ü—³` [ÏÔb†Di\º O{ñßë7T#Ž%\bíî '󗸣 <, wp›LÀ`âý†~úÿÖïÏÙUÕÙ\™gÌ¥sØa‚8ó»N6¯Š%ª¨¶}Ìx—K2(êY–S³§ EuqŒõf ¹ÒTf‹|·«Î„7Bi͇ê vD¥B²ÙÜ9 ^`^B;BnüªaY’¿æá¸&çÿòÓz^Vh´µÄìdj¹àŒ Ý®ù‚ Ó;ô sBÕFH¼¤Qæ³¥`ê r¿É8Óœðò¥×–2Ú8Á0ªö-w/´ASùËß:_篰~yÏMI,ˆœAg —î¹÷Û£!®¸Óúß¼NZôý´Ê݈7Óº©¯ÙsÄJ´i+‹{9'œ—–]˜€ü÷â˜^2Rt`uZ"÷%óÎM$é Æ: °OÜ?ÔS5>RpÕûÔË:ù¾}ðg© ;0&æRž÷^2DúÀ<]—ƒX÷[N…ÌŠâ!I§ÆÅ¹h€^òͶÅÀóËo$3úW¼­F¿›+ÆTKõV_ÞeZÜQȦlQéNGçMGÃA/ð Ë }MVY=ZHgdM2ÐÙ4o¥Ö÷ç¶ÀÇ.£å$ØŶ°Ø»O sŠ;‹w"°%NËÞ°+Òœ[®€Å|ßcBvQ“uÂYAî®Ì”Ì)ë ðÏSÜJïó’C}ðáX‹ÙsÏtÃygXÒú{ó‡Õ(üɰ MÙàµB´E¥‡xLàÒôUÌqéšÊ¤øÂ¹±°;X"·-N¨Á‚ÁÔYˆ\‡kÌŸé·eRd¾†tê4É깈ßT= o0ö‡iÃïòÀçõ4Û·ÿ” Dÿ5l*èëxY-ßuÅá›’ª7Á`4HrÛü.†$ƒª.[ -^$dr….fó"šV±™öd§¶·ŸÙï φkó_å!ñ À û. ÊUyóήyC³O´œ•TîpŦüœÉÐ}0o1’À¢8ðFG½ ŠÌ'Ñ4|ÿÓBøS΀#×t½ªÔÕ&ycŽ…3–ʵÑ“Æ\Z[ño:€EòzTHjÏIª™ ]×bç‡8 OpìhòUëu½Œ‹¶“ õ΀¿qos‘¹2œ ÛÙÖyƒÔ˜ëùq¨u¥gÒþ×Ú÷@µ«½E%p§ºÆNµ*éB7¹‹¾S牉íAg¸3²£Q}Aö,u¤ç‡x!”#ì$J%ÿ‚l„ä×z ‘Q û³;1­ §õÿ™r€Û•|–ÎV“âà™kWFÝKg&Ì0м¥íž/Z~OÁ8ë‡K<>Ç +[= úŽäM> Ëh§;Ù™V·œÓÎâYÉa˜ØD¢ŒªcÜv—Ò‰ ˜ãt's|R’Ï_ü`KXiay[` SÁb'q¦e™´öÕ¡šÐH‡ÿ¬üñ‰9‡ "0·˜ϰf3vh8¶dh½«ëö¾RTÏ*ècDzCÔš#izÏi( s XwÿªŸz…“P8¦$Ÿú›V½Ý6®Y‹-ûw¼ß~iÅ|ɪ¾~Ë!§òžç¬×ë¤ËåKOúsãó·Â5zýK¬7Œá뾩^§rÚj¿ÕâFÊ©"9”¼;²T«¸ÿ_óÞ´$EÓR¡o¿<À:‡+\ê‚Ç ”íÐ$šÎèõî~Û1’PËZ/ 5Š-x.}úýíq2Õ‚ìHpûšÈáñpŽSòÞ«ž1Gǥ 3Ây/^·æ×ÌÑ©™®íüXà” í9Bqg ¥ .1eSi¼çy)Jí<6wÑ)ƒ~nw1yÓhàœùær éâ}ëðìj‚ñL,§é­zåÍ=)ã ¯]ôÏäM_‘qàôð%?¤‹@=}S“•­Ä‚³…‚ãGÕÊßvŸ6Ö>ùÜj¨ŽG”) ">G¾È£Ø¡)ß\€ÀÕsN´«’Õê€gPëÌ!7ŽßÿBAqÏwˆŸlüŽv4ÀêzÜíÞ‹™«2¿µ@p¡Öá;°;ö‰.¨?+×aÀ»õ¯Í¥‚jÀ™¶møÔ¶(4'?Áª¾ÿ·XQ©]Õߎmexb‡b,L9P¼*™5M¯7ÅÕjrÿß:@nu*û§ÀtUŽ_#óÃýXe-ø—õ~UVV$-æ/»æŸÌôK&' í×ùêxûUÀ[ÐÕ$À’ ·>F«P'†³…l D“ ?;=“"-#ÁRþ§È9%ã ºt@Ñ_­d#®Ó§X  Ä+‚v=¶·¾eÍUàçÃàè·!ýä ï°Sð¢ÌÛH&õVîXøVtÒxÜÑ[5e|ñ5Û=?QVó`VŠÀ~h!CÎVš[ ÎB¯ð½/»4QÏŒúÐºí·ØAüYî!ÂÂ/ŒÜÈ{æVlWG†RŽÑqwcâc0ÔÁ¦™jæR°Ä€,F!ÍÅý¬ŠŒcÞ>@™/²_HøW³ºùþh‡´êâøÏ)˜´ƒ·Ìœ ô¾:äuLÒfŒ¬ûq̲>bo½®T¢´Û ÈOª*Ôa=A79çs&Yp$yþSœqvuD×Ï`Í÷è "¾n¶R§4l#Ôèýo&ÌNüÌøÈ=h9ÉÍ@€©®BŽÚž¥:U) ÂVƒ–X6.Ä$¹FÍUãø­îË\Þb„dt(/¬"*–MH£hªªg¢~Ì3ê½¾ŒIµ\%,}û¯zˆøÒGsÂcCË’€‘å@[ q D™XµP­Lìï²àÝ2Nž6rk/2ê=Ä´¤8¤ÈŒ¾9àAàÑã;К6°+| )>˜2š™ÛN.Úk™–¯K Ù•xò;>l|]¯a=ÉZÒ²i­bÅß, IáÞ–°|,Åb‚Ý@$.ÏãJÜù&€îÿÜ_¼­>Îý;E1i@ 0ËR=ë;H­sÂë‚4º=¾V(C ¦ØZFU@.™/¤BB‚è—°[Štšµœn»o0D'£Y´^Ç ˆ+]3:šÍ$þãë7¦ùeÇÚƒã©éŽt€-…£3}^C¼¢Ï˜@ÿ*gÇ­'ýºkR+”rÿ›~õYb¦#!e¢ÛJ~ÛꉽY¾§¤È9ƒÙ°*.ÈN©z0Ý Øq%j`÷uÏ´éÁžŒfˆÌžhÛ!¤o›ÖXWmÑÅÅZÄ“òìWµz1éä5ðOû0„Æ9 ŸA ,¹¼id…½õ«8±Þ JIâž`ýJ+=HÙ»üç4Ì·s j2FŸaùNj¯ß–NÐŽGº¿,‰š@«Êÿ¿¶š@÷m ´–¥6îÕÝ#ÃA¢cÍU.û“­¹Y瓎C „¥ì¤AáGSGËLjSˆÊ hˆëSR˜Àý¯F0-ÇM<é"€ƒ´‚5¾ëáÈ&Œœw3¼sîÛþ§l¥ µžJÀËwŽÈßðä+ jt¯“à‡úlÂîâ[We ‹ú->.vHYÛ¶o@tО™FS_ ¥Šnt0ÏS®Ó¢æ£€4(ÁƒÈº”ߢÇ­åÜCÎ}¨Ý[w}¯[ÔT8;¹¾1ä<«U-.f×§·Ûþù. uÇ5\¥—ôWÁ{ »ôõ4#UäzMEdTÃqŸ14°öŽõ§°Ñ`§U¯ }eý•U6ù?NÔBtÐ1‹Y½zÈÄGA¥|·)üc Ï¥^¾S³—|.ók¿‡Ky(Wɰ…Ížl“öx_åzÌl0Ò³¾¬ôä\PÓ’~}r‡‡OA¦¥t‚‰@áÖ?p…È«(ñ¬SÑ8£É=ÓΚ«ø†Q[e²{gÂêßcl9d Lo#•†a4lz#¡)ï&\mÁRežN&Ë•РÔûºùˆûÓA² 1½÷kB‡Í‡ ý!írÆ(“´]É”âs‹·÷)Y!§Tª\ˆ ¿ÀK ðâh8Ý„4–*ÙÀ#zï’Ñ©&üïY‚ø¦åu)‰…;ã¦7Ô²SƒËAà5”yàò5³ªæÀÏçóÁG䑃ñöñ©‰»C: ¬bü üòˆ )iñb5q”kðEí[êZ²¸ŸØ:—Ü´.;Á…o[Þ>Ǥ{)ü\ëž×B*‹Ïb\Âï̺ÐFªÖ½0Æ±Š£E/j»…7~ÁL‰3nÕ—ë@t;[ò|äsÕRë&Ɇ¯=*UNù{‰Èçe»‡dÍ®^•& ,”ìç<Ý褒FÆ,D&_!íç› q¯ Í*ÂÜú Ä/þ#„w}+nÌ}!L,$Ó¸4üê”UògÚN:Ýòºï…Ç» 4&Öí”À34ÂD{Ä0ñỌAŸßaõ?6XjßÝâg’qÅ7~ÃÐXot_o ^œþµéÈû2é¾Fn1¾(XÜlm*Tb²QDBú§ônn†íXº|‰… ëzJB>2TŸ¶¤z>ô‹?†p6¯6S(Lö“OrîçúHÜ-ÓÆ>‰£*í¡«›éˆ1½áô0»CcàÂ59öµ£ò~‘¯ˆ]k¿ðÜ¡?–‹ÅçK†žÇïdpí^¼Äè ÖõgBq­µqBŒ9×·6^)ÿ¼är^]æVKe JbN\Óêra Í\6;°•Å”<¦É)a½«}X¯Õ‹÷‰²Eâ§i%ÔÔ8lÂ-,M¢!mw÷¦y&ì±ãßÊÃ86`5~hJu˜*±¼:¯äRÄ!Ú¼8Õ²HFwg\ÏXeb(™¦|?A;@õ|£ûáÆ±ce ±|uÂ&ô¤ûÿ;Z2Ù¡éŧ8r­_èrÁWFg—Ëèþ‹C™ÎV0D¢úÞ}Ëmõø-| ê/}Í.?•ءƼö£ÖIyìç‰Îɳ˜›V€»GL‘`Òe.|ïJù>j_#÷Ê9V£àöQÊšZš0¥e|@¥fe\1BI×¢±`óJö¡ÐL)*y‹ØŠØx'ö$!åS©sÆŠ –ÑDÓ&I\q¦’IY³¥%£2Ír°{æÚæˆ`z4§í„ezõshbÊJˆËzžçUT±îxáÌäõŸþƒ“û¸ÀÃ4–'ò )·®(u9d@¤úiªÝHo²ùÁàU ¾ö|’õ£¼çp!÷g÷°§¤ Œ€¡_)z©ŸyœÃ#/<ÂÇzB^ĦDþv“ï¨ôókýañÚ¥ÜÒ¨¶ñ¿•ŒPk¦Ýgwš¾^£Úß™§­ÒñúÂhmoÖ~ƒëók9C@ÇG]»ÃÓ¦Gê8ÕT E”’±’mÙ ñ¨è¾í¿|áÖ½Ñö-*¥}©5ºFO.æ·Ú”»DîˆõŸTõÁM—ˆÀIS˜0|9NYñòcù¼ê1MSƒŸ9°#F_~«IÒ;·¾qŽoæ`R¶­ OéP°ÍŸ çc*X¾Z‚FÒûý{çÀËXòòÐ3½`·% ÿ ×EgÀ*ÐU_ÞˆûòÏF > ¿°2X‘a²,ÞYM€Ë)_Ôåèþl€MHf2>Òª!åmäѪ¿‰â÷ë”Uó*Á}Ï»¼L»§‘fZn ÂÛ}VAجUHnçìí^퇸Šý¯–°,ÿʹvæÕÐcª!.™ÂðAf§ôþ縺¦2CwØav7±ƒø·TÅrÊÇHÖà\ RóùIÿ€£Ä__Ý­½6ÑÃêê[¡_Ã×ë°p’пÒíš™aÕ9B¶±_pFB¶ûÑQ ×ûÚ1 ¶åƒz¼—w_2zdiín‹úYnbÍÖ2 ©ÇܘãñqìÓB$%¶ªZGzüÙZÁVðè N¨btòÂš× Þîx”h¾G¶¾|bH„*K„¹Ö¬a³›ÍwÎ÷Ï]\ ~òÙ%·€Å”HŠ#¬Z{µê”TÀ ? î‰t €€¶ÁaÍ¥Ëwn¶Wå¾{wÍET³D6¯Ž‹éeL³I3!&LÏZŒJf(•×sÙX[Iî=5’þÈ6f³j©5Ýh6˜èoVûku"ghcö5î~^Y!\q <‰NÖ úL9Î~;ÆNBòQyø¬›œ;ÎÚX¢Þ“6%ȲÐѦ*‘æP9€]ªæ×VQ?Ø‘¶Y?4ù™§¢¼Ó·Í^kUBÆf"7›ýÂÞ'¡HéÉJ2ç~55hãKÑL!+³ÉÖ ã–‹¾ë§ôPš§2N%u.ÈLJGËÁ_éX(®8.Ýø™ +×ç¤qOŽã(˜è¨¯¼«ôahU*Ìóï:/Ó-Okk¯ŽËeš Ï4J-"Yåow°µÈ–ä!இ†KŽ›>Á*…“ao|àÒ€²-í%î l̽*¾ ÷ŽÇñ>†V;Ð$yËÂ9‡ì ‹á;¯+•µõZI”-Õµ ã}'þÉ:z¬ÖžŽ7Ym &g}°ÍédjââQ"µè½.˜Óž!£™ˆ©Š5³PÕ¯þYÈ`™ö1ƒ¼½M¶˜È)ÖÇV‚.åºÝö×—ÄàröÈ ±­µH4• ÜÍ/~·TÂ'ýoaÌpº ¤ÃTìÐ÷8Uâ}Ì « Í÷†CóxSt[ð9  ¯,hKò«ù§i¯0ŠìÙqƒÑRnºÔõŠÄóÈ`—Ó‡ºd±Q(Ýð/1Ñ¥å(“ò[‰S½£@2e;À®/H¯ìèù¡?¹Ð†×xep˜²Fl7Ø16}yóOç̺(B&<¾Ã\KzÉR5â  T 6ø£_™ UÁP'”,‘èÀ'̳{ì4½dkÊñcùý‡1>L>£ñT“ Ò%—c’ñ *k3‘M²Å~N77®pùÏÁPÆÓJ¼tÜ]ÍÝ•ª¡pxµ_ ›†~ñ·3¹-²Àx¢—Y·ƒsu N¿0û½Üj|gºZMYNˆE,´{.±{™|BˆPLØhÇAÎý+óÁ˜žBfÅèžÌW•6°ù v/—VÄý°æÔ¯.6‚PWî\WáOÖ\MºQg1Ð^Õ  d9šªƒï™iA~ÒЃòzÉš)Ä’¢x,\ª/>ý–›‘£ö_yÁíð¸†lË[!uyîÀìÎSNyíº ;ãâ|ªÄ„Úi¾À‹ØHøW³­ƒU­ h{?ožèª]Óö5ÙÂTMdÂq×_D;—7Ä÷Ú8†Vú¢~Ye¼\íÄ@kk»pÏ0ñÆq¼•Ôôw4êÑŸ½˜ —f˜U˜k¬ž)B¥Å×JF` ÖN²ñ<ÖóΧòˆ1>Ó:c%/Ç´L1ÒÕE‡)§ˆ‘F‹bš¬!y9_ǺqÑÙê¿ » ëLfÙb¹l#^M9öpX—“<.ž~ïZPz¸—àË­Ù½·Þ‘Љïês©™!ÄØ }úÄîáòûÑ9¸™Â¶GêšíCO7¸MGÔjAàK1‰¿V+oüì#V¹¡¦772xµé¡(«=ƒåOÀç1ÿÀH¡E§Ó«í0C&Cœ™Ùm¸+I”|ˆž:ÑÚc¢²v9H«z±{¹kq„, `‚s©.äHÁgI?Ù‘’cª •a¬4ÖÛ Ä8|‘ëJŸ‹Rì:Ø^åÉ×óçCãlwÂj ÎÑgë çý]ý}–9;æš¾f¦¤^Þô|–5*2H•šÚI\dB»/Q ?g¢¿pïêb8Ha.bœ^ËÛ}iÅj—£y•É…³_¡RÂŇs[‡ÁTQë{BM‘øH½ŠQßËËøKëµåݰ]¦]^lê}X>ƒDî' ¹Ç$­«´8ZE(ß·ÊXZ¢ÜÇ9O a%ݧ/å–çb¾¤îŠ€0×ÏqyÔØik1@¶ÿD"õ=ð1‹ÕGœhùõQ\Püý§È‚Bj“›ävÉß_=ù†Êφ>Í«L1yaÈ ³¹÷‘ÔB.½Ÿßh’{2NE‹´][ ¸+ØÖc™IV¾Qý6B£n"ðýšÐͯÊÎ×,‚ ô1/q/Ú[Ë›uuе"ô/ ‰PJîU•LÆFq”D@üãÀÇo Âbí:0Ú žs±ÖpÙ=¬„sPûèU† ½xžóß]cÆÒÔÍ] eèè®!YÝþûžv%sH^÷üH¹öW<·ÿ‚:C^Ìm€‡£`=ká`N—LH'ë',•cÉɤ5ýUìÜàa•;!„ó•‡phV‘MµnØE¯—ÉïÆ*'-^–rDð„)dÂå~®ÙájUéÁ‡ MCŠ&ÿ`=ãõÃóð.;cåM´·œjP¢W­am‰ï ß*w‡©ÏHkå ¨‡Ï²•tª¾ ëîC˜ÂÀ·Í¿ ¬³;Ú4f¯™ÚÃZN`ŸŠJª#E£ûWeÏx4)À~p{CBØ4F¿¡SŽòæþh vuöâ]+¶\D²zpÚ—ÉÅÄ–9>×ÀV08W´•Œ&¼³&R¹Î&Ó\4‹2Î?™µ¸*Ë`ÝÉæìP´\?'ʨM¾t1;Ðxa0Ú3ýïˆù/)#Õ:+ûÜÏÌq¨µ9äž/«ª¦h}®7ôÀÏ\%?}v­=õ‚fTŒõº¤ðþ:„¡›×°?ú g—9–½H7h¥}\´Ébñ‹xTlc\EïQhé¸á„r<\:Câkô„¶lpW1êÊ;RÄ`þ1 àÏ×'dolzS§|ùóÅLªõ0ž`u )B8Þýĉ°äИ×JðXùÕ€‡êëœÆôé"ÅùùÕ?4T…æ"¥um†Ð‹Së³è[XJ±g0Å¥.޼ÆÛl| àÐ gZ…óy«{<<  ÐLa^5O™yGÐŽ"¸@€C^¸/ɘø)ÀÕþNÙ‡¨+ŠHƒ]èß_÷àþ·l™Øpcmð°iOn&ç­0§cÍø°Pkl²nþª0dÝd†ƒdY¨U#B'D½uÏG}¨ Î?oeÇ\ƒ¯ðwZ /€¯èð_;Pm_—5æk7ß?1ž#£ôl¿³|QÍB÷hÊÎ0©bM¾;øMNº‹Ðû‰wj“ë•tqðÍöx£ÀÎÊÂX$¶D-'®õÍN~Ûùgƒ¬¬AùBq·p‘J+WÚÎAzY\ø6$D—˜ :¯Åey˜Xn}Aˆ~ÙDñk¹5€J¢*HùZ¢›{ˆ «vv³´!8nþñ¨@†lϦOš;ŸÈÍLýšÿâŠ1=íI™.kB:˜X,KruX*ˆ’  ÚøÎ—^,ŠÜH“J©Kìy—ªO÷à/ŠUZ| ›ÁÏo )Ö¢¡·»ã“üò ÊaÍÌþ>š~GùoG *º4®sŒ‚§ IÆe–Ý·™ ;@¡íóÏ30Þú yÑÌB•ËË_çB”Ð*¿r¹–Ú{MÁôõÎBüæšek­àßmmë&6ð0ìëX±‚‰ÚŒéâ‡ò(ÝfD}§ñêè‚]IŸ&ãüÈþ3 dÂLÞ@Šr ê•£(0wû2×þ´ì‹Ç¾k©ÂɾâÄ ßP†Ò2_®VDóÿq¾þQŠ÷'å,cż²Ò¥œK.Þ!†°&ùd}¡çƒ³‹ ŒY$áß—V7“Ê~&M}¯|p;!³@42 'Fuó`¬øÒÖAÕÏ]“€“Ž  *Ú>ožBDcNœ#@n,òÍ$ ß>DÏYr;¶-¦r< #Í(Äç®´µ{ Qþa!pœ;f)š¹Þ ›Ä©¼”Ü_·éf@ß5nE˜>¼Ùv¶¿ÉŽ0²YÁaØ(H¶ö“ßÙÂ;S ^Râÿ®t²Ì­\¸LVU6*}ÿ)A&æI3±Kk똢_NtÄï†ä„ùA*^ù<±BŸ³µ’)œcŠQMeJHÂ$1ƒZJ‘î}E*‰ÏrY•*=5±óQa8ïÌßyHË ÏSæ ã_²÷*]?2±€ 4½MÈl¸Ó‘ѽ—€Y¨hL6=ȇàÇKæ¡¶™{Êf ^‹[ÒêvS1g!“X¾G‹Y’£™«ãì‰÷Ðq¡*ûØJ#âgÀMò”…yÎB~`”àá9Ê>êÖv°n™}Ï¡—Ðl·©–\¿ÄßXn”]xÕ§0-ûï ÔˆVV—–(Ò?—‰¨ÿ¦øX%`yØh[a"‹èÖÒo‹æ.ª÷ƒdäÒˆbî„·ÃÌÀ ]³û.0‘úæþŸ×šÇ…E¿ãW¦eÿç ÿjq„ˆ€­Ÿ»³6MåÞÓKâa– ³•½i¿^"ÅIrUž=!Uüh· ý,ÿÜRL¿2ÛíPØ{NÇ„ýÉëåÔ8@ÝŠÌ=.ø/£öÝ<­Ò|ÐnÛØî# Ÿ½vô¨2y‡hî%€½Mþ$‡»•¯rC}Ù‹Ž²ó«/à¨ì‰âÞ+AÆÌm”‘ñt°ž¨ nWܽ‹0±p`÷—ì~ˆŠb7Õ” ÁL[Ü3ïQÉú’¥b{«Ó§¤,|p¨èĆ„øã'(Ì%äý¾› }„õ*H¿‘Lî"ÝŽ!B4uCöxÒ]1®AIöúþì…-Ð"§]³_±1̹H%5ÕE:#NPDyXâl+õÏYc—³äãÒOã¯ÑÉÿdT+8b‰ë‡L´—HŽ£ø¨èCéŠÉ«²èÓ(Ôå}–¢ž]š~U(ÎÔG墹]ÿñ«®4¶K­œ'š„sÓ'\U~ ß½ÄWR³ejIž0és›± ž¾+¹] k”výESþ¤ª…´É®£4ÁK§Ì÷WÙÄ]3M7 ™¨ûˆr½úPó ÝãDžï“Ar’@ÿ'áüù)øyjà]Gðó·Jð ">]Å$î÷IÞ‹™ÖW0†²§6´ul/Šÿ;8 &ÑÕÖgø byâQ2Ĉn,é)]ó'è^ݳ=T’—5è£\-gL@ñoèrüïCè—ñ“MKz ˜ì~PA¨ìxøÁJææ†N1;1…ù“8~ìaÓé/6ùªA ójsNíLOûwð"t¶²g½ðí„We…YÊi—¡S}{4)’?7„ã‘ð?( {ñ›¥"A b0DŒ'- #èQ’©ªJ§é奮6]I>\6GŸ‡T3ŸÍ’:QLßšCàÈ[.ÚbS€çT=„Ö¥hÙ*Gü‡}'mj« pÇÔJÍ«pezDÈst3‹™jìã&KaT-Šˆ'âÏêØù¯K†K騋¾ó*ìïÎØò¡Ï?°(°I´õßà~Ü…£BÔ@Ö\þrÈ}^ìû2 gšõ’õÚ<ãÞAA½çåÔŽ¿Õ3.ŽxÈNg8@e5 ;ÚÔ$ù#LÃ3T¬žIù ÿwêûz2ÐÇú(ãj+JûA».]MéÑËB Z6´K-e~2”º)“JàŽh—÷>·8~Í7wËŸÏ¥fÚ\rEÅL»[6wøfãy})˜fþX‘f,aR9-Bºz•0©,›ŸŽž hFÇþ:…*HιR×èzt‡é*;eíeQ4w7Þ‚6K’øæ}EþÛs«s4Û)^˜_Ö.³´µQ(0°N1FEqDxŽP–óÓ×äX-W‚,HŽ1•’‚Y#4«¦ÍùþGíý±â.ÿã±Ñxûý¸:g¨Çã_ Ÿ§ã]žõš¢dYünw)‚ÊûO©ÐC\ £I ß ÛÍžsNÇaŽ”ž»Mý›¥DÎ ù8@ÓÀ_ •®G3Q«Ã“® Wõ(†rÏWv èÖêß Òƒ%øåÈ«>@A6-a¾Uú¹rt³yÙ±fô9¯»G ÇGYµîP<®ÔG¼비;~-ÿŽEÚø‰ËNöm«9ms6%Ríš’H6Ê€3Tß^ÖÇøÄøBbèÆÃ¬ù­ømo™5T©§¿Y'æçó'ðE+•€J¶5–¨V<¶ñŠ(d^ëøÛ5¿ Þ(2œƒ<â²Ä›„Ëž¥@ ÕìM]>ª’=W¢wdÙ˫ƇXïÓ*>ÁA¥ÈkÔ÷&ŸA½r4¥ö ¾-XvÛe¦ºŠ£ÍKèŸÌG1“ÛÍϦÀWÝðãO)5†ÝkŸ¦NM\ Œ…[T;âd$¡/…™Ó‡ìiÀˆó±ú7ž®}y;€àªÂÔ®¨(ÀgB•…3r˜LM;æÈzEK¨i™Õ¿?=hÅJß/ @Ï;Ñûé©ûã³·b´‹»üNÛ;›ÔNÄô˜HºÐ¸!ëíbš@—Yé·Ü¹ÃX†gâNwªQߑɦx JF3ÀA†å˜†_}ϳômm dù?ó•Îàð°*™ó¦ü•ý8zÿ「9àä# rbÚËý° ûÍÇËÉs°Ð_QFŠðö{|,½ßÙÇØä±#ö_.Äðµ@R tø@=æGtPfüÏOwâé‰xÚyÏ¥ v$o2û¶ ¹ú ÿfbF´¼Öˆ9ä'šž¦—÷ƒtr”ƒ¬Æk&o\ݧ~4AÑ ¶Ý•r°$‰]›S?·{Ï6ÏQpfcºV‡Àóû<¯¿#|ÙO, m£4˜Óˆˆ%r\©Ñí¿n°Ž§bè#2ŽˆVU„ÞóǽápyÈw³Š¶Šu\ç$Ò¥tÉ ê°të!Ü]|;¡ƃ¯·a[*&: -‰à„q´ß÷»;Úé*8d?Çq†3+ŽMîrË"Î"¯¸5PØ‚ †÷¬Çn2tÝŒëÐqöÎXdƒªà9«‘ gæ~甑†Ñéjµ>ë¸ÇÁk˜³`~?¨å—«ß_…ôä–ÎõðÖ&ý©C%ÂU¦R ÿG7…êݼ; ÚØ)yFfRÇ?Vc~œ7eyR¤gÛ°7H#,êéŽ!=#Ž KØ·. …~šMÉ*@x£ ™Ð°Bð¨bÿ)•δ|×€ FÌÅôö†ƒ/'p+W–(v`i¡lìC1¿EV¼ùá¾;•IA¿É³=ÃâËÇÙê5Ö³v`6ʘwiZwó¦[­ëY-ˆ7~nËY­¤Cîg–j8P(1e[Í|5éôðxZï¸Ý7Ì1›­$åüVŠY{»ÕÃÖB^QÔyynWÞ'8åÁu䎵00ÀÒç87œþ.ŒC ¢ÿA5!b¯÷庬ô?†b“¶Èôt ýÉŽÏ÷朷ÉÿmU/P—H:_!ÈdXÓ3.§`* v[ïÍ@¦ÇNÓE7±>Ë¥Õ÷°ÈïÂâ;.]CüÚºÍØ^®iþ‘ïÈ•Gì:Å·WnΚ¨s€ëò¿Ÿ=ž½¡ÿµ0ØË<‡Ô è~Û[iÄNCí³ üÄýÅÑyÉ+8Öµ+G\>CeŸúèׄ'ß÷™VH£Ö|ìäG p1 ŠþÔ1þm$5+[É àjÈÍ^—`†p<8IÀguÛ!ÓÈW>ÑÊX г<=x46ûœ–L/2tñóTÎÄ W‚+:¾b#@‚Úž?©y½ëj©\(˜•Á•„LÃÌ„B`åV ¬«2“p¾¤§ñq"ËŒ3Ú6Øv뽨ÜLzŠ”-äHqÊä"ˆLé‘´’[±:(·)ƒ¶éaÉñÓJ‰£Ò€ 1%ü®4¾=²3ã{õí¾V‘®iÜ.pÜTAŠÖPž¨ ··(],³”YMYþéZ’ñ§¨™Ðøy€B¥í*hÿ­Sg»®ü:n68ºˆXœî³]ê·ØsŸìÇDê]Æ1VCÇhc@^¦(Wg*›+žíîk­9È4-$õŠ”×ǧ·2†$0gH¼O£i^wŠ“_¯þ2”b¦çp×¼55:¬va,*‘¤%ºwD¼X«öS«}:ÌÏÓO¡5ß³/Úm|@[bÝ’b)Ö¤¬$„Ya@ï¢XÑdrKEÚ‡#€˜‚‚&þ^'`[”FÕ>§K´˜‹ÒE6) ¨<ãÝ.ý^8Fö­šˆíqW24c½‚ÌþbxsüŽÔÃ*³T)¢X‰Þ²óαÖE|WÚ×›Ö’’tr,fÿŒ†"º­º“]¾/ô¬Õ!ÍLèZ©Ü›Ú§?Esý• Z˜©Ý~,µ¶DLO-})êß\!n¾çˆÝÔªœúð•<¦Ö =Pzp¯ø¿¬¿m’¸€˜U Ù7Q»˜“^\øçU»§fˆÎV«Óˆ¯ŸºÉp¤UóiÖÏà4y;8ÞÉNÄ$Ý6Ú®Ñ"éÈ¿Ô2õÊ?þ2pðãçàÓ%°„c¦(ll4`Œ< ,=h¡Hpâícî’Yh×ß³­úŠ.%8Š1 èÇ}ãqº«7ÉðâÔ_øeYCç±UF¨ŽÛ‘5ÙqS@2ÆÅ¦ßù(9Ê®‰¥BƒôT’u¶˜¯"ƒ“9׸.ÅfT½¼Èëáäœà‡|lʲ˜µ¾øÔƒAAWð»óïs$Ëo-^ü½•*¤ºçk95 %›'å ¿côyñîs¶ô̤lw¹x‘Ú’êë\¹.l¸ÅË7A‘…ÂeŸ\@$Âatì ©ž ìÍ-sfÂ7•ûÙ>{ÁDeïm„™¸-Ür"šF÷‹ñ®{7 2f¯È…«ƒF [£–õt•¬7¤'ÿ—Í)ÔLŸ¢ Ã{©ÊÙŠÖ;æ[;S{èçÇg‰Ä߯óHã¶EÁÚ ¥Z¹1 Ú Y¹6Ĥ9ŽAàé˜/Cùà<í Ïíü‘ûMp§WåKÕ/2/\Õ—™´}P ³\:ùˆaŽ;OÝQ¿Ôj?²âÎRZñ2§¨gjȪœÞÎ4¦[nDo 1ê*º7P–s*O™Æî¯MÇöuWäÞŠæ“«E ó噜úþ#“ö‚ &ÉË©ÙË%Š `P#ˆù×µ›¡Ï 3ˆtN(€² ˜Æ$®àÖ ]®þº+'ÞäÙ ÉÿK3 "—D±Æôì5‹=8Ïÿ5,¼, ‚”YÏbHMÙ-=µË£Åá0¾8“=/·9q€JËS}ÀP¬”ë¾m'0݉=ªG0¦™lãÀˇâ˜bD<®ƒä´Ðȵ#æúز0 µ&eâ{—‡W\ØÑdµ}ë”XqC¦àe»ëŸy¥ÏÚÝ«žZªÿ°}ûj H” ½ïþÆÐ÷òLÇ7YòètWó…‹áòÈ2ÅÿDS`OΛ2ðÇ:µia1Øœf]Ê•ÕÈ–˜Oý»Ÿ7§*¾¨:ýîMù>”:lÆiŒ ²†?ê‹"Û/§c×0Ø´Žà€íŸì6bRH„ùÓu—ûq—ƒñ¼ÅMJT¥nˆòH€0Ó˜öƒƒžÄç×ãáàÅz UöŸ/Òжýjº àx fLÂU8áVø›èÍkÆ?Èo",úVcšçóóeUo±QÙú‰–H¯ä,Ò ™¡ŒÖ‘¥Ò×üQAL?‚E‚)xÝ"•’ÐÄß lAòx‹ú5µ[Z&#‡š£ª1˜ æêÀ¾`6L˜`r¹‰üH—Õ˜KBϣ̻S[…CNãÕ>HŸªÁþeNŒ ")²y îùË =oku˜Ä”Wɵ! .|:—Bø\. ÐÒû|UÙ’ƒÓæ{|£ýw$­½y7ã¿]r·èŠ}þ®ÉÀN¸‘nÅ=éI{`ùI,Ú—ç¥è6<æIöý^5î ­f¼6Ê&§åž‚¥µC®ãTø³ÕØ\áÊ"NDл¶W^CnSQE1•¯SrG÷p÷ê ?‹ ¼.CCcæ‡õ\©ÔÒo1üÊŒ2³ ˆ£¼ŒLoIŠÝ·ÀµŒ»‰¶}Ÿi‰Gû-¹ií«Î'Ð0·à:%[ˆ!&O%>ubÒeɰkü ª8ç÷B]î¢Þ¿Œ6-a7ü‘> zø•"š#Õ†]{D·ÚýqêŒTŸÿ5ƒñ·þ,+ÓªHÄÙïжDZ™.Gÿ6Õûr=‚2¨d)2:h«A#âdu0›]D>׿ÞòÌÌN$Z¶Æö[_|oJÄÞÒr#†[<ì*Q}_'‹aŸ‡¦ÙxÙ¯à1(e ªO8ÆÎtçÒ5ÂrŠ÷§*|Ý~Òex5 ã³ m;ºÿdÀ$˜p…/åÄ=éÃÄ‹°Rs€þØQÜ[ØB+E‹ODWÔ=w†ññnDMgæ<À?£…cºÀÑ/KUõ| æ%6¾…¹£©B~²eãAFµ·^Ætúœ½;\–÷r‘c÷ï«"Rƒ^𱹎¿”Ž’X|¡ßÐÑ;à¼`A§å’…ap×BmÄ¥ŠñÇ ÒEƒw~z¬$óî9ø'SˆØ4Ñš‰Ñ„ÍŸ¨u3øÆIÕ”¢r½]Jù°‡.¶fa8ÍÒsîùÿK8‚HÜ$âóz©ò_Ïè¦  7¾ÿÍïª_òõ4d÷v¨™Îˆ†Ö @õ¿ 4c׸Ðɘ‹ÄHÕ{1Z¸E† 3„À/Z(ãYÎVD4f¶ºs#c팹—xóT³‡¬džå·orÖ×øÒörÓûXÙxŒ-׳å9Š€Þ=AÌøèƒ¡ú*ãB³ ÄÅe› ¸à‚ª"  8_h}Hd€ Y™¶\™›ônlio7ǧÕÀ‰±Î6“+[¸ü3²ï6™œÞ¶0QÚœÔXÖ“¨{ 41R„UÛ"bñ"”‚¬¸Ú›:Bváí¶ƒ•H›Àñ5%=l F<Ë]/žc°F§ Q¾-9L¤ŠÅÝpaó«ù*z8R´È÷ºÔ½<Æ ½–d$£,¼Îû&íI¥™'pÿ‰|ËŽNƒˆ…?Äè+ÒrùwdþfàZÐa2$ÍŸEU× E=Ô„ÌFâ^HîÕÝÖJx’'Cut§2Sñ¡a¦‘Pa©{$Ø-nfA8tOê1§´­põÇ»Iö H ÄÅÒ]ÊvÖ­>dÿ˜UP½“žúÕCü˜äñÇgÇŽÂÞIèÝo1þ‹G ]Õ¶Îa“ ¼PŸáÿ®ªÃ³&è÷…®£Ëá}D+ò…ƒL¾¯mP÷pAjÄÖcSùÅaþìQµ\˜úVSÿ1”ln0’y(vF1‚WÇJŠ¿ˆZHœn4êQ{v…7+Eˆq^é1 ^ÄŽTFIÈ¿—ÂéФ‹dVÄ'I~–1ÉyŠwND{¥Å®² #ËæFØX2;nß9ÉôÑ6i˜Æ‘$„‘2åqW¨ï\괆ƾ}EXD"HäUˆÓÁºIÕÉvMºœcvÕåµ`NPpð¢H;­|ÅnÁú”.KÌ}e_†¿+•8x¦Oè”N±XܲE؃8´]‘˜—FÊsT©6Ü–1 #ÂMù˜NæÞ_ìñ4H¹ ƒØC>ûxµƒ FNuIƒÞî.·m&·ƒIÍ=dì¢ï›VÈ<éÞOxÊS¦{‡‹‘Z?{(}Ÿc„(#Ѝƒ\òÈ0^/þÏ|àøÝðNQûš ÷C˜ž~2ƒ™i ó†ÛݸÑ1ýÐ4YÛ¥àK#8W]ì|äõC¨zg@ò½@Ÿù­y6G*»¤4pq¾åŠ[]²5f­Äàx,µVWq  1÷ÁØ$ }µmŸÙRQƒJ–Ö ¢Ñƒ–k+yX§àyª«8ûª¹og¿×Ã7†Ø 4 K•ÓÔý8Œ—¡AP²WÈ™§Í(Ê‘MMú±E‘±(yÁj©4n›\o:ƒîMÚvð§]K¹ ôÄ%[‚í53Žø8[Wf®øÔPnóéˆú"ÇËuYZü"ÔM 'Þ“5ׯUj¾#‰ÏþÉz[F*/•¹ÙF¾q©¯Ä?ˆIz8ÉŽßÙ Öâ-n1ÙßœŠc+9%ÉãÇÐAëmþèîÐJ‚¿P¼IÕ½$ïÐF€¹XòqQ§ Üè%áÆQt+·?L`ƒÀ]FX\ÉDös¡´1Íåf9Â…M ¿hh€›ªH 䎚ãö: ”±Õ" İ÷e{f¶ˆâf»6Î"Ëõ¼ âvhƒU¢÷ê?óRÞLìŸÝsî:$O€ÑRV0Ôl4×fðˆw±Š7kLpAgeøVïM`F¼HMÉë1H=[Ð};‹c M´]c5È?J5z(9GÏï,eë‚øç+¯Ù&·ø4*¹Et@19½ß!®»ÛÆ5PS1¯÷=8NuŽþ|ÍòÛÕ¨Ê1Í—eö[FV8lÔ´—Þÿ0A ~ÿCɾ©åw†ˆÃé÷ |æ_¨Ôì?ù_‹ò`?eAyÏAäË$À•]j³)«ÄåÍ9‡*)™°FZVJH²/—¾ü¼bš†5< †£®°ñ½ðNÛ¡ÍOžý:Ê oaý!r¼Ü+¯ÅcLD? “ŸX•é™ìÊ=±I{)˜!&‘ú¦­‡Òº/Pëdjz4—¹}‡­ªS¨ƒ7ÀLü‘Í F²ß÷ Å‹¼ÿñ˵“ ¬{×Ò5i‹'If+sn#ÖÍ;;¢ûÔ~s¸q>/ÀE#ãÆ›üqžä-§Ø]+LD¸Ž]+Ü|¥W¿² â#PÞÔ2b R »WãœãbÙ‡âb µ… Ûw]Û;äeê5^¹UJx8”PøŒ›j6ÌhU¹Ü4KYÛ¶7)°6õ.)Q!2¡¹’ÄÈx0Û9ϧ_uº¡JÕ‡Fùº`òÚ„3O–°ƒêæF‰£k¯÷Ë{º; þôa9"ha§wVÇÒ£ ];7ŠûïÙirŽ»~xRf–ÌÞ£á8žN§£Ìˆæqä´6¶ ¡·Ã)ülwfhLˆucNCÿìÞþ “íÈ# \O€ƒ°JÀ}3QdìC3.lÒï4tÝQùŒÁñ—½Ûl‘BrDd £:ì}!Æ·nÓ¼à!Œ4ÒøÿI”³¼ÐÖ46:/c‡,}+?sµ]8ôÔó=µñê¯|9I@».¨æ”ˆ |Žódžgè3!j„õóŒ—Ýþ÷ƶéÕponlYgÙÆÕ íǽ&®Éžcb ¤eßþÄÛS3õÕ^Ä”4ä.ïw|7ì•ù;sé×3^Ô œz¡ñ]–MåIj÷8©3–éßAmq[oa@ÌÁAu©zŽýಽUÖþ¯ÜñÇêQÝ'Ê}¡VÜ=qW¾Ã(…ãܵPwç¿ê3Ò¸Jž¤bâG\2”eœ[¸E*³ ­K›q8ël9žîÎ>•×–Ÿ€ÝæÒØÕå8rÆN Ú-"Èwft'ØWý¥Ç€åÇx~0ÒÇm‰¶óóºÎ(@ß’ü¸ŽÝÒ^Š\à½`KMh#&«NÆMÇk† Ûz6³EÃ‚é Ÿ0^ºh⪾%Ô„õ5îˆ5&ðwúb¬|¡|˜ ³¯(8@«HhÕjÜBúä6”6ð‰ ÙÈÓûП»¥šT׬OhëøCà…ÐJRÕŠöÙkÔ`2ö` þk,ºPÌoôbƒþ‡b ý Pb·Ñ×¹…l‹~aó2ìå`Ž&PPsc9‘Eèt\ úùòõ¥Ò¨ë— ÃÂÛ:W…Z7,’I8<_“… É®cYpޱ‚‘ÁæÊÐ#ÑÎò®,&›–6A¤nÊP/¤¿ÖÒäF…óõ4†Åq¶HÑ3ºïåt!ÿ-šœU(åäáª8§Ÿs‡¸ŒÙdO,FY2êƒéãXeM_À “¬;̹LaÆöG!u¿lš<¢Ã{š½b°­Ç>öž©Ðê^ežrb¾íVŒì¼‡s 7€×w4HE­‘Y¡î³&pÏ h¬ƒ »ñ¨§‡ý`ø…”rc¡’§Ê„<>[ØVº5ðãljó ñ¢ˆøþrì”Slæh¸žxfòú}QyN8¶Û5ÿ0®ªðë¬à+"øƒ…¶Í8c–ž—Z´=HÑ•'µÂÏûè“éš —Œq#²îÔŸVšßœÄçÒuªÁ¿rq½+_ð°‡]î—«‚‚úªÄªÓYE¢Ì¾³ènm]fø¹î¶Bè`^¾ù9”ËbÌʾ}ZKUôI%³³AІTG°É?dTÁűg_iâÎb½OœšêJ•…³—Žh·!•ÅÐÙ,—’àd“íOEŒâÓ=4/øì€ÜxK¤E›É«ÇîB'MÎp÷Rýœ<ÃRVY‚ŸWs1ȪÛbÃJ|‰ˆÚ-–ëmbp‰SèÈ}«ÝKR"xïÔ¬˜e”•âk;OÓ~¨Fm7ûb§¦3Þ®n+ªØ;øúeýCï@ÑQ`·uÅhÈ`ÍÝ53j«1_heþöUè¥-çPñ`…˜¾‹É®1é"6±ÍQlîÔð°`m5ê$´SÆ.ЕÕ\ó.'+oWÀ°pê#ëÍÿ]¤R{ö ö²MÄXœ\Yó\¯VÚh[YÖî`ø»¥AiÐÏØ‡Ûâ..ýס%4½Ò9m{W]ÒÒD"g:nCWºjÏvD\Nr¸ fÁXÇÌg§‘èµc¼¼'—Øê§Þtupí¸XùIý1ÆÛ޵µEÌ ª³.‘ûÙ›ûX„½mV,î$Kl0OM½îÅ(B2ž ¤dâJH3𝵠ƒq{:¬ã~Þux!L/ºÔãÊPê8(ÞÎþé:.©SÓŸô°· ]§“ë­¸5˜p‚°FÅH–O¥'@HÖˆQbk¾D-ý^ïš„Äߦ¸­jÚýà|ÈÚ`à껳éXÝÔ›³yr!Ùâ]¸ìÓ÷ØPgà‚°¥ FÙ«1ã[5šR8ø†(=žäXhÈ;…!DSþ0•¦5Qܤ.ÊV-ëÇ“²å»–1Z$šÁ¿uÁ&±+Î`Güié5“4™Ë{ÖoQ¼«MÏÏàýc$[iZ fþSYý UsÖ%_-"—Í„Úg©+/L»snBdºM‹£a8*üõÚî1ʃ|­ó™®ð§65Z„ÂY 6Ÿ–çõ¼©¹­$ÞóPHß™p €º£ÑsðPàÎâ½k…>˜S”#LÝ{#’Þg*Ç€‡šr…Ìjaõ¥¡fdºx.Sõ°Â`^§eG0¶S’SÞ‡3ÉÏ݆Ñl«~nå?¬÷XOÓ­ "rt}€šBê?vhUKú;4‡Ôº—^8°3'¬u¥—ü«ÑÛÈÌe@ÅZ`Ë?çcÞ ­È̵´ÃP«Ý’lÖlÐ_zˆÁ™ü Žê\\’•Í“´ìL3Á¦þKÄ]+yýA!&UºSt˜Ps(ºÏBD [Ÿ¢˜;`‹ý)•-èÍ]šÖ!\tyðm5¥Ç–½•‰;ÝÖr dæƒEæ¦K[ŸÁO¦ë)i‘…øyîÿÆš©ßÅ¡g§˜ÎèÕA!,ü˜Zò×"‘òüÍ»NÚªL±÷üÌøÖŠ7U±­,DÅ ÖP4‡Êµ‘–aIƒæAkoÉR7½e^ƒP¯òäÿ÷æ ]uUDË?ðžÛÚ,9åQd¦?4H®).Ý÷Õ!vØÙáO…>Y;ìF»ó+Ï“]à‰[Dõšg’~ü[/$uó8Bmt½ÀÐ*ˆÔTRçWÛVrp&jÆÁSL ç¦ðÔ­ßíú…ƒbtiŠš¡öS•´ja/u}~ÚDˆÊéV»ø^!uâÿ›[z8‡ ì´1ÜÔžPA>Ôy4 Ê$éwDV/ù~‡[T,¶{³¶v¢ø9^+L;û4¬ô4b<ÓÈ7Þµ< ÐËYá²:!ZshœX“#fÍ)®O;š¤ÿqM4#v ãfÀGXIeÙ[˜Þ£~9g» Y,»IFlØ8å;[‰!¥3MæX@i¼»~£#ú¯%$–GœôÞ8†*éТë4)¾!¥yvÇôwh]¶óˆ "Úß?âq¦¸Çéf¦ÓÉ›„‰ÊS¡áåRÛ9{cUìó>,] Ɖð¿÷i’rf?«ìxÁm¢ÜÅTËPé¹RÆé1ƒ’C[&’‘ÎL?hê9º¯óg sŠát4¸äÒX”4|³Î粆[-^q´SJ0²Ä²\§ëî/“Æ/G¦.úVÜsv&n.-DÓ§øhÿsõVn…Eמ¯‚l\ΪÄB«ô ËHÇ@ù¤vcÉf´ ³éÃq[1g»{òi&>rZ“yÚ(L¸A(v )Å!lím§Ù³¥§_›š«WnÑ6ù—¸-âr5Ø’T™v2Ñ Ç˜9ÂA¶jõ¼„é:ïv2~éÒ5qHõßµ¬+š1Þ‰f9F¸¼HžÑÑ’<‡g⯓œ­¼'IÎöŸ[Œép¢‚ÑÜÞ$$49fŠúÿÛ©kÀÀÆ7q/U e’N,lè²ÎKrI S=C½Ý€ßXû¥üElÌ«)‚CZÖ¸×9 ÿ£‚Q*lÉÀO>c®û±Õ)f^À­U‘ú ÁŒéHµÔkEBËêú’ì,¢ÉOl>zWã7†PFE¥UhÕis‚Õº ®Sx; •Ûœ²7€sË»†‰m³Ÿ¶~ZLe­0“šnÙêµÊ~;ò×IéÝyÿ½!æÞÅù¦SlØH»&ûÏ3+PùÙ ṙÚ1Xc£ý â…øR„¡ê™Ì ùíoDqrKéx‡?‘þôÖ³)›E‘6ê$¢>QEC1íÀt„ˬ>§Àí›Õ )r'Çšä0+í¢ ï»iQ8bY–‚4:€»09x“ôeãI¦÷.ªàˆ(“ªš§¬…‰¿kdµ¤X-hT²=Pc?œUÓÛI-ˆ@øÒ!Ü0\:‚³Äs³›þ ¤ Ä'IÙ8o üãâÝcX¯g¶RæAðý|Òæã9é ľ1Ú—c}?cL ¬Ÿ_Ãcסӯ t V.ª“ÒÇè¿9úÀLW3`¢D›“+{‹'l¦W ÷KOsÏÅp?"£ñ8תä}¶o ¿Ðó+‚Ü4õ÷áf¹èÿ5¿‰ÏJïNnш‹b ‰ÆÜžÆP“ÿØß6ßwR“ç&m 7§Ž'*ÑA4ö9(2~¿"âȺæ" ZÕ¹6›© h£ÖVƒÛ$åê¢,DÆá?œ²»ÀüÖj”²ë"÷Q¢cÎe‘ð:>aSÖ®ÅÕ] üjR£éÅýf¹µ¼ÍFÐâ=žB±íñçn%sŠÔ€i~Ÿ„vv/zTIÅF&É÷õÛi´ãå.tÒÆg Nµ¯dƒ¾©˜|yÛ¾°önœ÷hàޒ0Ù+á*,[^ñF´½k¦É²Œhô!Oyê6y”‹`>!7àî^i0Ð!õlý`J®³œŠBÐ÷Pkþ©‚>\Øt.'âÏm¶Ïm[T:â*Àðâ€Úi’"-‰ÏùÎ|ä´ìÉÙ¹ÃÂðþkù~Ú³Œo}ƒÍÄ)3$í†À M™£b¨!à(w8a$ ­Ò8^©ˆûšs æi¦°’…ĉû¸±Ë³mDQ·añ£D¡'½Kš5ª— cq_K>|“ðç ¤–•½Ìáa§×öl‡»j戎I[˳R}z®Ÿ- ò@ ïÃ!ÓÃãÜøZ¸÷ýéð¸ÔV¯XÔæ÷ü—{lŽ. ‰´¸è¯ÞîC´Èog–8ùùÌÜš‚ýŠÐΰÃ*çL3 4h ¼1lSI4 :¹Žd Š¡obŒouv°þ(ì$åY0|;#ÅÏ…‡íõT±‡)¿›öúü¥Зi›´í˜,Û2"±°ª¸Þv÷ˆÇ·ÞD£µjï1$ã˜wˆ%A Ná P®”ïÿýÅ_“”Êom,rn\Š>·Ÿï1¥drE›X,Rg/…ûD §ÒÒ›DG%F-£œçͲX§Ì2=h ‰‡Ü‘FLÛBl¶Ù½¯ßrqÙÄYËè¤_9ÂvÛ fâ/x:éjˆG¬ïtš–y]'ßkLx èêô•AšPOЏÓQÅÚ¾ˆ"ˆ+¬,É™£‚A€¯D9]g Úï`ë݇ðafcDÊôrET/ùRÊðÔD>M[A)šÑjqÓ˰½Æ³ƒÒüŠæZÄbbŸ|äYÖFÿ*©¨MÊnË}Јy œ"¯t¸Çfÿ—oo„’²#Í 1"‡Í oº,v·æ²0…vÇ;þ•ˆ9¯XØíŽCz9jŸ•Xtòç7*5ä² rÕÊØñÃhn†úM›d£{ñä4«Nùì³VØ}´hË ]{¤È›— †__j«œ>Vô¡A2³¦mó'õŸ'¹9´kÐ…“Dþ±-L˜ZôaËàÚl&”•ú8—¿C´ðÍ‹S‰Ä¶þ¤ã 2ø=#Øß‡®Ž¸ºnÏõ­dî^}íeóA(ˆ$ñYØß7ð´N :_láÞÁœƒUEó ,•?öø^¯þ•‰¿µ/x ð² lÖ!§x™j¯AÁ….¶ºe¯A|z5ýîIBåWo=©òn1Û¥)­÷ð°^¯ô÷b›þ§æDäå¥fuǼ¯Lbä Ýw®›¹Âü7 Y €ÄN¤ýò¨Ií…kÛ_9Û„Y@Póg70µKÈìLXæGñ=%Ùû+P³^å1¡BvÔø¾Ç=à”ê´!œa.5¹0ôŠ5œ¡µ#<”Ä2ÜÙð‘¶äêÃ]‘äZK–Ç ÎffDN pÈé½f,Ò#?Pæ.¿ßT©"šãÿÂù ÈKnâ• Ð'÷ÇÏE:‘ øX<^KÁÇæ Fýªq@X°…J5ÒÓ Üx®cB»Šz¥%ÊdÛÊék/ `µ†«÷²»E¬7VÈùB :1XrêÿØ-Ã+ îm0 ÑlÆ € µªÓÅv¸¿‹q¬¢IbÅóô- ~dkÊ@_#¥ŒØ€«R,{Zéy2MÐEç?[‚‡«ií¼]ÌIÁ_(Úèw‡¸\ø‹}ö}t¸êŒní8³®Ëséù‰cyM‰˼ F‰Ä®î¬Ã@ÆØßYð­Ýr_üåÈŒSàÊ×r§1 SdTŸ´OF™ïôäŸÙ*¿B|~*tÞ4 ñö6eµâ%nªvbÎw •UëR ÊÒJªâzÔÄ|æú2£/7~Û¡)S·IC· ë¥ÆS@W*§™h tD«2ÐñÏjœ™Œ)„ŽÕ KQ©ÁŽ º‹à$›:C×Õ]5IãVGÃæÔ`ùÙ¾L‡,CÀ¼éóQfÉJ7ø¯›Ô@=Ü«Áoö9š*‚ ‰œé5f·ÞÎî;®Æ£Xø“•¬›‹BWÒ@Š‚%*ÂMªƒA áôЈ5€W¨˜Ím£YSߎÎÍÞÔÀ”Ü~ ©h…B®Ž€h=à„“bN6X×t.¬rbR ]œÍY&¿œV×Hõ¨Õœ׺ Ç䈖ΒÒIGwЀŒ¦ÆW*Q›¡–5æfÀ€J¥®óटeb&Ê|õQ†¿ÊK ‘ ‡P³9ßÒyL*ÉŒ \RÀ¦Ó§ë”Ÿÿav¢-ý¤ÎÄGÑ‚¶ÛNT¥gj^§=[VYÓ€æBkûJ*«ˆ‚dÆ~²ùÜIw^ƒ‡«ÿçAA.Ÿ«8 îæjâ¯Oúë_J‚ˆÂkfÞ–«xZ~ÝP¬û“Ì÷€íåGÄ>5tê™ ³ )=¿¼¨" âÛ ¬«nG`Ù~é—‚ÝûEif•Qƒ§ÎR 9Ãâ%gE[„ëÁýþà÷tŠ™cÏÞEu0èÖM#ªkÜ7‹3õµå³ŠÑ(Ó3ãæ¯y6¡׆â6*EvÊ¥èì®g¡Uê+®‚QÃð ƒV Ÿ\¸­É7ü\– ÄꙂ¢€:ªÙíʰ<9‘ÍGÜ÷ë ÞóÚs ì2t­µ“zŽSH¦9O[„QBf«’† kŸZ’R †'ãèôÍ=ÊÂÈh´æƒ:®Æ“ú4vÊ ¥”ãbƒJ#Òèô XYõÜk‹4ZŒ´F1ùàΗ߷¹j²ϯ±7ã-ØÃH|¯FrÎS;¦ZÃãRæÃ9¸ ÷ðÞ¢•=îž:á“Ë^Ò‡Y~2rêkBK}&tÖ2c7!^Iyc2Éûܧ\XBe.ø×æÅ0ÚhÍÔ©5MJG [œœsÚ)Ð÷´î*Z“DušŸ 0ÀC`¿]ŠîYêBך ŒÏ6•EO°¹ÐÑú¿ˆôyh ³y³@Ç„ÿÓ1v¸´W¦:²'9ÛMbà,Z‘ôBû$’ΪÁæl¦YµÃ£Æ§9ÛHàõ}'¾.pöâšóÒÝÍ)ÉdÒýqƒI è/CDl&Anâå"_“žµñò €Î\4ûyŽBÕ±ëÈ·ÿý…ú±r‡Qòé·§Ï`ìÀlÏû[‰ÌÉsû™µä} ÷`•¼ ‡{‚Ô•Hèï†F¸ž¼?‡@v (Ë(Û­¢€¡kø°gÏh †x,Ý…‡½Éµ¿.zÔ»ïœÑ„8„9ª\t‘½È× /mÆr{>jÝÚáÞ”Œ¨ ‘ÖÈG´;§«8#9𻫇ÐLª€89èÑ=øÊFIÜåþÔýÎ,Z×Ùe¨ü€±bE†‚:ÖÅè‘fÑ>þ\¯^PuDR&ŠÝ?›?0È*\àÄ iU|^F#ëí_í¢¹p` lý#'ÝášL+zÿ¿àÔ(_Ï’ÇÅuëÔ•‰sS£2ámËXyIP¤œæçÝ_Ö8Y0ð³–!-Ò·á>}çŽ «ñåŒì Xä’ëdÚ z¨ö‚nNF5t‹q´ì—VzŸ:•ƒ>±¸+e#CÑÇ`ß> }Y*PuœZI¦u2œ¤«Hc<˜1IAyaý[=9載 mXÿÎ §õe?QìÞätg´þ*æÒDÔ¿[â’bWá‘áK“ï>šözÝ©Ì<ºIX=è÷¯µ­òø)€ª_“!*aÒ÷Õת+‚´ŽP\öÁ%ÌI€MûC?RÇ:áe§VÙ¯©‡v®Òu«Èrn Òq¸ïÔdŠÒO3Ê$öºRX¤˜ç^ð²FSVPHqþEÉ'¯®õ_ˆã¯í44ã ש—ôÀ}ÿBˆ]6þIBt° XŒ‹;ô´/­»eRš/†C©üç Ó 0 »q / !Õƒ#tœ²!Wûè|'1&îNýó•ÔÐ(¶–!‡Þï/KîYüÖX¯‚du.Þã?T­z…GŠ0 c§<³¨JUqaÉ´—À9d…$hæxóE½c¼àž¾ÕÌšHŽÆºâØžŒ÷K£îD爖ökExȼhƒ 5 Þò»#à‚5 ÙˆH\ô4¿ÿf&K¹gÏ{• }&'\.õ¦l_ÙáWNPöWf:uü“צÔnu«Š!Pà:i€  ¤êcêQ©v­@œª`’#ï$gô«¸7°Vl<îwóS¹¨°ˆ»%²W@ÄVªŠ‡†•ŸŸ¼Xw_ê«`ÚZ b*_œôò˜=äï7Ø(∱¿DÃÀ[“̉Úþw° IT‘‡PÍeЉPµ‘û¹»MØñYZÁ"²4,ð]1 ý|ºCúŠöhP`bxh¡cr !ëïö…FØïïLKŒ¿‹é ÔrôveÒ¸ûKLñ˜¦éʑ䤎¢Ns:¿ØçÑф݀† ÚÓþ6›tS‚‰õFó¥¿ÂC…ÍøGï4 Ù+¡ðÑŠ°£— ¥ÑÅ%±–>uŽÑ¢W£ÌÂöãÇÿlÅRYcp¶Ä V#ÔÜZ,`ìî3 Ç»|ŸpŠZ:ˆEå"{µf+Ö׈ã BŽeµ˜÷»ä£ØÙ–CNˆ0ÄøbÙb=Óë‡{É—þ›`c- Oö!þ=û$gµ6k}d¤Ã½%i;ñzŸú•pÂÔñqàóGÙ·I¹KvP° æp7ñ^Øk]N » DhR)vHàÛì(·õpºþ¦4@?¹$º½uÞE\Y›æt·¢P­°ëgXÂi_ï¦÷ŽCûp:ÿP™árÁ²:Ku#RÞùFPÕÅúÔö­9œ*VÝÆ¢‰µÉÆ\ünà{üÌ1P>P|AØûÉ<õæ3‡Q±Œ(éèUMÛìp0Ð3­÷%Ñíõg·qò^ %•¬:ƒQ„¤|Æ\xÙåß_Håf˘‘Í¿fhŸã¿TªÁè›J~r8ó½yø~ù÷†)ʨ ’"¹6é†Gu*O8ƒ<ýŽÔ 2Ýk£Ö¬ÓýeíœOW €˜ ŸëâszEL‘¸mƒe‘œ™¾6ö>šýËÈD¸—ƒocA; î^Ì0³›6 Î©eê¡Áó¸uÁ+ìOVÀ‰ëŸ— :öÒ—· )\yHÖÛ‰©ùêþátå¾_Åûût¥ 9.YÖ 6“8—U¤ÆYûW¡r>¢ K‚g6÷OkžˆóYyýXA÷sãÊ ¸PYü9 l#øÕ?¥ßõù×&Ë™iÆ’Çõm#(5¡UÎOHQLý†;ÕîL¸iƒµÍq¢ó-ZÆú£Á¢C¨0¾Ÿ'JYI¾àFË®Þ×jGäm›ë ^ 垥£rMsñƒ€QÉ Š@¤tY]U£¼laŽ»0Ç)Öó¢5u·®¹tˆ›@¥ÝÅ̧hÎb#»Jv4\6ÔA¼¶AóŸRµ³•bÝ`9½²Ç0‹óÓëOAayFA¡ÝÜBðóÝ÷°W| Ä&ŒX=Ær0&8$ ghÎa”N3h`&#avz¼áOpË(4Ž?Ì—eXÌg‡[uƒÎTký¡¨öÜ ê˜t |ÊÛ÷cü„ê›K/Å™=a„ù°~ÆQæ$ÅòMv-µ~ –¼ËÚ0á'\ÓCpj«Üµ:Ø ÌûNÄÿSN³¡š× urÚQ?0ËÜ;ÈYøÒÑ8²¸ Väñc”륕 ,abòÙê8¨bHÔO'â™[Ê7oD¾[º‰&rbðÖuÍü!#×BœKª R–®Ý%" ó»l…£=†Q‹q(Ó"…kEU»ðÌ„»qÿg£e¢Q3©hTìáhì9-BhKó™œ öCÖÆ•?¥6¸ß”‚J'ŸG º’˜jæ¹T·©r¹‹[5Åìj\š‡|æxPSÿ9b¤¬rJj2ƒçNK_7NòËš<j¢þ–®X µÎŸ™oÛØèàhëé²¢†ˆ\ÓÅnß•*!DÂze¢ã\¡´L*q c—ï¯ïa¿Õª °fç—¿5“ [ÖÕyC/\‚ÿd_§ ¼éW-*ôŒ•yÅS&F&D5è— fIãàÜpø‹ÌæP¤,ʇc ~ æÜ£3äÔuë OkíWÁ­Ù–ޝD˜|0^†qC)kãêSàëÓ²øk¿/§ÁTÚ™èrß›·4ãfÖ¨_Y&uÿžq8Œ~A!“äɬà€ëCc³y‹ÍXتäÆYåeÉå˲ӮÖK¨ž§6^~’UúÇÀꛦüJœª¡t=áñ!gïØ®ÃCŒqOj®Û-`œT ·‡ ÎßšHYÙvÃ/u‰ÜÓœEØW]Àì/9#Rßóˆ4G(™@…N9ôÎHì*JÄ\Û¥Eéª íbËEsFÒK!¡íy·”\m#Wo“6š a­@“yfšÈDÑ ýn!ÀªøºÏD«¡{AÄ-“ ½(ˆJñÿRrö«ÔLÕíÁæWK;°Í"Ó-¯ lu—ÄqérÄìVlƒ¤¬„ ñ]äTaTÉÁ@i¤EhOµó%€î—VÔ0:, Ç›xuúfE>Gÿkx£Þ¯…J»{­‚c0 –Í>sݧÒpɜ较všÀSĪhèþÏnÍŒ€ë¾”?{K§¨}®Mÿwꦀã!ù»MÇê²è|ÚæÁ³néš`éÜ"O–BÁbÖFÈ+?}_½œW¿£N‘K™kgßôæßç¤fÄñ¨³ë+!{®ps…ó8& ¼©ŠáC¦ adNÜÓA÷Ý+¬VP]5rŸoË̦angê>ýUýS‚T`ÒæºðP½­A –¼­p*©ïñ¶Ž¢aá!ö @ËÄ’ Q54 ?ÉÅ| "ˆæË-o“<úò {ÂŒû+S%³-¥sT"QÏÜSœ€O“à†¡ásÝsÉ®ÑeE‰ÚnäC–…33Ó¾ÌUyÚ­çì1ɸ`³J9:òO%L|˜õI Àaÿ&'ØÝó-„:­ÙB™»»OO­"z^êA)Z©×K¤ÏM9KÉyÜî9åNkŒdd t`êMp \üm–·;8‡,ù†á€å Ý:‘ÂGºÎÉ.ˆ³Íú"ÐDìÔ)ÿޱÀ×1•ÉrŸž¬O‰ÆöhœØk·´LnVÂIiï,W†2‚a}©Å,]x]»Ç“7[¾ê÷tFJßáH{&Ú+qÛj¾¾Šýèók Oÿ߸YG]˜Ãÿ@¸EÓ½DôchŸ+ò„pm9w?u(ªWÄ;@#÷én Ö´ó.žf8?Xœ^“ÉQ%°±-Ϙ÷:IþÀŽ/aJ²cêG ãSHç§?¨×]ˆü©Wqä ™[ÏúÃdY~BÔS~´)·¹á^Ü0"ÓÑ×Ò8L ½yGGyK*÷Çп]΃³6”xwV!xÅÛ¶½œú2qzÊó“eW•ÑKµl=\…]>öáTØÌÄq‰ïÌ뙵M‡„j´¿ŒØŒH¯ÇM–lp•a¸m?á)-yïò¹Ä´ÃPhQéO†=ÕXä¹'{à´¥5’ŸfÐëM7Uè×ò%N,3ûŽO?@#,"ê¦+æñlö8á B€FýªN¼2bv›«5Ò1°(€7ÐW–ôWÐf ñ4=§t²Ç$#çZÜÖÏ¢#¨‡#ý“®¯9‡ô’71˜³B’y»Ðds$#ê #ÆZª¸‰i=FJOIBNòè/¸R†©þ¤üͨ,q ngÉG:çƒñr’5´¤…ý4÷kzÙm°ž(\;–Ÿ7%$c/¥¼éR&ºm@u.küdäÀ‡«ëùtÝeÔÊ&ŠTö+^ ›Á QûvµO¢“|=-ÜV±B¹:ŒE7Ø*{¡s€¬†4ì\E˧M¢ï@lƒM;ºˆŠXl?ûgo9­f8I5Šj‘Âÿó5Ò,’ äÇë¦kɆ5=ézÖä?T§?UÐ¥NttÍ/iúÜ­YŸÚ߀b•8†æ:µÐõ†i HËôœôØËŸ••àa”Ós=ÿþß«NK Y•&§ŒŒ˜¡ê¾™op›.ŠyYú…Y@¨D·xû<¦"-2„†•‹EÒ<ˆÅ|U裋½\'cP퇤™å¬ìÝéš¼S”ër¼®×*¬£!5>ÅxIl C×øÊ;»ù<(æúxF :OÎz?TH¼¤y©™¬Æ—X±„]f8ĉÛ9èmz`ÚÞ‰½¤jGßÿÙVo.k«“š|BÞ·r*ëÎüóÀ ¾A}F\Wÿø¥Õ ¾±mb­?F„ LöÚf·v%‚±!xžÎsêÙņˆ0þÈRvºtň›½JO ë…õÒgBò!.R¯Ÿï´EÒ—§RžÎ³üv±tTºD^phöµ~êzÓÇôƒ6äM´„@λ-nu×ìíRï¿Í7ïÂöþÉ]rõq79žÅc«br"Á‡ç×óSÁÈÑCÑÜȽ‘ØÀ1ÆìreØ4øH3[¿m4ƒÌK!ùH{¥b‘×¶f*=šJTbõŽáMÚP$gÔååWgϪ”ËK{ç{ÑP|Ÿb¹Ýý)¶iñÜo5µ_ÙzÍԜ隳AÀ ¢¨’ÀþÔF*È~¿È<œ0²,1(ì­Ñ/Ç¡`×_¿½=bUsïYžÈâxŒU5Èþ£-°ÉgÎ/`Ü àþ±kœ5«”®0a-ïÂ@<›ØšÚ©8n …7–œôS× ûB·SCo†å¢ê׿'Ù¥•…TÅ€|wVÄàV¤ %€kqÐÜèï„/‘fYÆ{Èx‡!ÿbŽñFGûv)Èm#ᨮ,nXÌS\¶\R=)/Lhø$-Ñ3É­ñ3"Vf 2]av«Å’>Ë, }Ài6ܾîÿ J0î72wmÜ{ùb›êÜBUh”¿JþHÅÛD¶¬+UŠH—×!¦\—5Im¿¬´¹˜ýêds™Ùãõ™£›yÑ’~.ºÏ³Llº½$ÿêýœ;k. Ùyáš àúîÌT-‹äÇþ u­(SÔDXÅø¯ç'I(WÌeý-‹KÀLØàž,â$Ëße ±B­µcQ £­¹sÈøT*(jáŠü£À8~3ÊÜF¢_ÝâJAì0Q‘?{ †®&m$%u¼þ¬ú¥ÚFt³£QÒ0ÄÝ•S%*ü ó‹Ý=&ƒÉñ‰ñ:›;˵é#” Íèsƒ@\šSé:™aÒ¯CÉÏ¢¬  µÁu¬MÏ^µ³½ 9·d>Ï%B|\@uÔpl6výš9ή¡_•®µÔû˜$Ö›û‹üEJ>Åú{t¾åÅ«Y0Pôd€Se«1ö«¦-À(¤ÆöŠWÑqÄWˆ‡Ö¥Á×¶xH…­ôï ‡äôª>…Ǧ6(›–3¿ÕD°“Bë„c¤Nr}àë43xev‹þÄÊŠ n•x-X%KÊ¢«ŸäÞ iÝĶrŒ;Æ@ÉhœC¹O ²n$!µë0ãY6×G¿¯w$±õ°Ã°…‘ú•1è0ÑEbØŽyF+°£+¢éâÄ_lY!ëù™MÊí:!ÔRX©QEM´hè:ÂsF ðŸÍÛO¦Êžî·ŵí% ñw™ïÒßíP û¥¾jšƒIÓ *œ6<ÐÁÕ“ mÏt)³éáåIÕ ”ÂØÏó%Ô4ªÌÓ ½“ìmÛ†ã~m¸p‰ dníbw]yØÛï`îÓê?Su6óa=‰×FÊZ[·95Dåo’à×ìå×&8º@BG³×·¿FFb_=ª€3hãp›¤15û¾wr傈†]çMò5ŸÏ§†‹öìÐE8·Îc¦3ÏY»G^ßR«,n»øŠÌ®+«ê_ FÂI¨§y‰Sypª¡ûÑû‚§.ÖåòD¯SÏ­kѵSª×XcÆopî¤ávº~œœë¡ ·ï…N1@ÓïHM/ «eçË’7¢Š“›êoäkg€Z%ücCkµæ¬Fb‰0/ôW5 –©8cÖÝQ*žWkµ0:¹ž’rZ…TÔÁæŽñ]nmwh¯ëÜb1ŠxKãÇÃM‹+gU—À„ã¦66ó·¬{ÕWÑ—5¤ˆuyý [šÊöØYÝ1©!Q%²÷â@=¤~8½Ž¦³ ꈨÑP÷ÃÒ„FuëKé*íO°ê£gå’|ÜÂëìÁÒ OÛ¹ïwû®¼M?X¹vê»ÌT?ö—z´ÂÈçÈŠôÀ<ÿþPt{&Òò˜z3ˆc6vzR’–ý}s‚¼½ž¿ë^?— pÆj²{8¢§F)ñÀï ýõÒ,cÑCW&¢Êo\£PwºÝÂê_¨Ø„ýÿòñL‘ì«Ý u𛍙!=1Cˆëv±måC Žt¦¹|®Tv,<Ï/& \˸_ÍgØ-0ªk6(ŒÕæ¶mA]ˆ¹®Æi“JÒ=Müúo¡¨`kd°BÎwvÝÔ+rcÅPUWª‡PÎÜ“ÍA[ÜÔ½.ÉPh×MTD,OjvSÁm@Š™Ý…g</£ƒ§ŸÑU˜‰íFÕŸ£ +pŸZ‘ù¿ˆy¹¢‘M1ËKø€JaÓ¢m¾§ƒ»ÀRT:]™iÖÖ¯ª{ã-'öOèïÝa¨l|õ¸pªÇØZí¶žz]Ž..\b5“²¦Öµwõ¦jóE²ƒË’:ùVeá‡@}Ó Ì ËF8p“Ae9òÂ㉬œr9r¨…ý@[²¤Æ0Y¶ØH—$œeTC6NGYg8…›uÿœA]]3¹"á&U9Žs³¸žë~ªÛIžË–‘Ú0gùÎ_íArP–Da-TZ]RpPŠr¹#ȉ'—ÞaSa™îÅߘöƒu4ú´FÔø2z1h•|ifTµ•í%•µÑ§Ïv G`âWáÄö¢…1Ð=k $ELSs»å30GS¶@[ó924¥ÿæú“Z% ÂÙke<º‡dy5£´\Ç´•Âd}Âýc_ö'žªVé¶Vj $’ûù‰áæ𦹠Õ=÷KëíÅŒ/ËêñLMØ„\-ûéÇÊhŒ ³“'è Þƒwø‚Kö>hXí\Ï6.ÖUs£Ñ—6Ö*õ\Û€Q)ª }qGt|ƒe}p|­4¼Ø8P“ÁïPøkH”žG7”šÉÿ hG\¹n´ øì–Ï<ô¬õܺò}ª¯_®wQiAšÍ}öëø¬TæJ pkö…úØ‘(Ãá3ŒÍÎH VœýŠ5²Aó8 "ç}äJi}j`_‹íþK*Àó¾r~ïÿúv^­£ê(ï:æÔlcºv‰JséË{XaŒnÆ ¢Òø¯+pÜ&‘¡çŠdRS˜­/»‰É0Ê;G+2ʽ×}h-”–ÚÃyÏöÔKh[ê¥ÚA¾Âj-ëP¨nerD_[h„/`ÓôpJôNÁO%Ò_qézO u’À°ã,ö+LiT#oËž$‘§ÈªXIÄS$uã6SôÉ•tè¾á`ën%ôƒ¶r¼ÖÏfç¸RÉn®²!‹BNpX˜ïht&þyÓ˜x÷8„Þ¢¯ÊRV¸9ÈEïÆ³Ë)²$)ß¿7/Šò•­cfÎÄ}$;¡xÂfžʰàe¿:T2ÿˆs“.ÃÉzvÿ%´|Düþ’¥¡Ø­v ŠÄÚ:Rë¢ÿE>ïã‘ðv˜rƒkvx>чA_AކƟ”Ü­rJ¬3e43‰t¢‘¿ŸyzêÇæÈcÖó„ÿUfÞÂ8AN94¿n”m˜'>ºÙv‡ûº^ÐÆv’*£Äyª/tÆúîã ¬o£þâi0HK*Jàs^dxˆE˜Ø§†L,õª¨ÇÊ©ã“Ãóp!ü’Òcû–¹?}jãøÊOË8ʇ©ë„a‹'~à—`smS?­i“éè8q´Â=”ºÿv à9¼ÑÔ²§«Ó°êë&œôQ<"V|²>_ 7±&ö+d^âyJú¥}gP8¹†Š²Ÿ†£]NLͤ¨¡’È7 CFùºƒró0w+XÿCÕ¢©ät„Ö’—ÚcŽÌ^|Í~KÚjF 1þþnV°pß—}a›FÂ^.Ÿ5;Í×Äž’{Î^rÀ´#­üS[}ÙÁ•Å¥¡N¾ñ?QrlÆm6܉ÙËwjÄ ´ä´'ÉWÕŸ„ÎQ¿MÏ…âé öÿ(«Pt «Ä²• ­þÚ@ãÑì’agV3Õšm~ë²±¸Ézuñ gÝw)ýÉÀa½h,1 J«—|²>ç Ý› È*?ÌGÃKmâ2ó*í«ÀcáôöœÚȵ{Œ×…o4(’šgõ†yp=‚vgõçä˜2ˆ¨±I?— !ˆP9)‘‰D–¿~^ÌÃýò ÃHÅÖ5ÐÙ‰Ïî‡jJÆ;^dÛN4<¹Gt<qW€½À=äuE:ü–C6öØâGã¸uH+£0Ç›œ?\’Ö™VÓqlb²º-´ÇµÁ!Ž;;`ç˜Îû-EжBXö3K]•9§³¹ž ð€Øf¼æ¬›qïšÀê\²Ý÷Ïc¤7»ì•{B9€°ösiªmÑôÊ(Æ?öÊ¥ ˜ª,™Í×›aL´íW±S¸$™@š,ÈÒ¢4ßQBýöçHºõ\y u1 ‹í¡O8\N9V©I8s„½Õ¦ôôÊôò~DeÂO¦tœo,´æ ÚŠ¤šjI×a¤ UVƒF)¯Pµo-݈ñÆé¹|—¬:ñŸÁ5˜“ë{MX^Þ®þ™–×pÔ§§ÂAƒüë¨ÆÓéýŽ2þS@½Ø×öÙÎy>žÇÂm©³ú ßjîñ³Š?êb‚Ä餗S†%Ð6v@ì¿`ùŽƒOQ·ÀßJ¡ž× Ê}ID„ª­ (×—5‡ ‘KVÉÆù“¥øÝ‘¢P×áIúÅeDD¹ÞõW¸ÓÏ@47åy v*q¼mïÔÜ£ªIO¦u±sív¨4;RE'@~¡hWnöBâál®ÔP8LðÞDÕp4Ãîã7ËÑc‰9èù{9Âçô£¾‡ûNF~# WhVªk¢$˜½A[«{Ÿåe$q›‹ú}Ä-¯îX·}gXß·óº@Ü¢áÀ®—€{M·•`ìAò‰å¤Ä–šg|¶´yBñQR×g š¬ØWØïœ]QI[íì”Ú´­úRuÇ~n ÿ TÆŸkzMÕ%þ¸ñWBòŽ‚LSc v~IÁdÝOm>ìzhÿO±ì¹wŒ«î:ok§~Ú9ù…èÓjîÔ™ËØ8«½}ÈÁu¡>v}·§Š´×I3+zeŒd(Zl –½»(ãgN¹÷T–ë|uˆ„[9˜Ç‰KupÆËPÆ@ÇÆB3{©9ßÓ'/¯ÇUýѽB6;J :“~Õþ»“hÄeÅ ¬ô4ñ¢‚SXé­Y«×÷G ºìu¯úr/sÒY‡ß@UË×3W‹ü¤Äº( XÈOñtõiZÊOóöjXN#Hy0Ôp6Üþd§ž%]W­UØ´Ú;ûYâ-æ&“§Š“;€Á\wâGù¯ A°D6̨bÊâ\=¨0vÑ.NÐ2WŠ×fÂ|öª¢¾ò‡~ÕYß?"*gøÀ¸ÖÒFª5€#,-} ²Ä|„ǯ¹`áA9v`šaúžÚ16|jaì zø‚Ú=6òm²ÔSˆ„ ëÅ&ø;ì¶±-¨ô ª|Þű“R*ðÛ…¿ÐÓsPÚÚ% €¦¼ZìO$ õÇ]‚SA‚'³5Ï7UIþéô1¬-â†ïDè)j»ŽŠ£ö‹’ºjnlo‘#0X”_ G!237rÞ„øÂ< ”è£ä†fUÇëþ tŒh4åè„ýh_š®¹Gñ:?9ª0¤åÌ•‰÷«dåXv_s\HtÌQä¿WKžNÎJÓÁÎïXTǦ޳Ÿ›9ÓÊËÛ²dfÓ‰Ú@ÄèŠ RûŒf\k<ë0á¿úµõUcxxà7w³¿tš’ÀäýÅu´0,«dÖwCG JÛ~ÆH@¢H³>oqgoÚÇ—&]Ýo^Qv­"Ðv] ©æêûc€+ñÏ蕪C²9| ?‰–ÌÈÇî r0RæÀà‘ñ©Ÿ¸…çÂïC¦PšàÇm[ U†ŸñÍ¡4i“0t°¥÷,¦JmŽôøÆqAì*Z°›$ÖÖ¢ïÿÎZãXMœž\MCÝ[è?êJÙYÂWC‰Þ‘Ø(ù‘‘'!ëÀakOã”òù‹ +Áø©wüÁ™Ǭ ¡ïx7Ñb¶ËÌK:2Ùa‰tÖ_åCòP$L^tuŸÄú5q h»Y‘ –(š°§AJó¸-A÷z[Ú«~ó“ªbGªàÑf(ÇAmwàFÅŠð,Ý䬌´‹£¸ìðÛø U¯‹žà¾EdK¦_*Mës0)GZäªÁÍâÜ”‡~÷ó ü¾Û^á¾qTæ… Ö0«À;3¯\¡ —3_3"â5§yãùTØ9‡ý¹ª[Ä®ùª$Ò#~Îæ×ãDãøÉÃ3p/%õˆ.VçVÊi¤_)¶Ôs>rÑ]‰¼’˨P0]©º8úð~4_j*?–²yjqõîá’·"ií;Ì_à—\¸ÜLa%ö„3Ó.¾gZóez§&b&®Ø€p8\î¡:v³½ù’tì_X`>:¾¿ÞÒ~Ò©@Šxžº—ÉæÀ¢¢ÂAxö‘~9òOl5™…&RË‹©ÅwgTr¯ìxP˜WµBxyžÆ;“<§êB»àFþ'ÒjiH ôP'#ƒ,}Ò"{èþ2=½­Y|˜9óé¥ö ;j@C?õ#·g¶zµó²]ÑgÛïáª~]×v4b›Ldzì“Ðð\^¡ÝŠí(‹æ®Q¹ÅhõÏJ؃ŒÉÿcDµÑUÊžâý’¦œ;+•­U#ÍØÎ³‘<]oœ°KØ-Œ›*ÀÄ)˜§Hw•$è»_¼E•`ÂèŽdÞƒ§õ_z¤Ì T7ÑYh|@úDœÙ±’°%:·¤º‹,ôSÒNX™k‚ˆUf²çqyî†@^ï- „Kã¹ïuÖP¶FMÁy±ôµÞŠnáŸ>ÃÆ…ïËN³ù'3„Ï”A¾=–Ôwµz+¨ÛHξy}/ú–.`/,<03ŒŒPhÁ&â:(™l_—6´B²Mà²HD~#QÑÓgÙ#¤ÕÐÌ`>¤«~í07¦N”J„nRëЄs2-é´l+ S!¾UˆúHeóÜðÕOuÿèwî»Êä[â‡| æ|@61é’a\dáÙ má–Í(±Ê`7(Ú½ÇKT÷[ûq±nDªûœ¸ÉŠŸ Ðjßtz!•—Rÿº7/ÞSÅ„|y©ÊÙ°jlJÄhÄC-KL‡z/uh½Ëóî1M£ãÂciŒ"3ÊD¼¦ÝÑMÖ2º6”¦F×áîÉhºJ¼G¶Èå㌫ÀCaŸÓýܵÏ<T?æÌ6™Uº5±ƒi2µªsãú,ªb¼/ÖÎüÛ…”kNPй¢ƒ\LiCI’o|v"ú?q¹®‡Z8%óÿÛÇôáVhZLM—7©Â” ï£›A”?—u'#Vb)§GN‘6£w-Íßïv FøòS&„ÞsrQ«ÝÙínÃz¦>¬Ù?6bxr"‡ÜrA,XЉ‚zÃ+KÄPˆ=ój½wžbÊ™XcšúĆY^€¿é—WFÞ•°nÉÎöá|˜˜ËT…ˆ™mÅÆ4ª1ÁeÄ€ºEŒML½djŒ·Járx1ìz4N: ”U_$Ët{xüº(UQl¬ÜÎX¡¡d& Ô(åjô;› †5"ôáEO'õ¥,5|*ǃÔ5J™nz¨´ë¤©è»L,ÁLFMô}sìú½3òAX«r.À­Ž¼™¨1‘¯4?¾<6ªmãß7cJðHH mKûn”gMs)Y­‘Æ.$ŽÂhÝ#$Í!†õö½ÎcEæ0;!­Ro‰®ÌíËu=tÁî›CfCV6`µWŒ>ðÐö Ò!Êf©»ÓÈI$u?}0j–}ïd†Ëé-[[ûß«“* Ý 1/+åtÓËEêDuy7Vg$E–&ÔÉy´IAÜG1…ÔqÇTxWuÖêv»„‚Nþ̦*n„ÊÖ¥IC ($¼š®R‹(±9Öa±XÞ$áî~ƒLéÛºe¾¤N˜Å;”JR Á|ÏôðÂcªé—­CQÐ/¢àÉÝ£4ªlÃOY,´Ê3皆ðyS…ØÁ¥ï\°Å qã,òµ[Ïf`tÓ½yMN™2$8OLûuØz/P_)hq “TeÖCäšüØë zÂk™ËÓá¼$v*dœ<ˆ õ-Bû…#áyV4¡±y,k…N)°üù)ì~×'gëq(¦ðøWKVb`ú Y×5…ó0*m'¶T?sÈ\ßëð™õž¡'«íhò Õ²/TÙU»™Ÿ/CGR&ÏÕiÎUíãŒ/¨‰ú¦tDo›8L“´š…›Rÿ×\Ž ·&&ì&”ì£cþš"rG1ë‰ëû8™€¦ÔˆD…ž XI»ðí-,¡\O½™ED2œœ<®º"‹ »BžïÒ)®¡t«Áø=k­µ§ËÉí]<×Èr™H3ë´B¹=g²¨33^î™ßµ¾Ôµãaø²˜ ¾tcÁ/–GùˆYä~ ྮAø‚vÞ*¼ûŽ41?ÜfäJI †» (^Ö—Ö5ŽÑ‚ÁÑÑ/¢‘ñŽÝ <~-©õV„€Ë «j «sÔ‡…LQ£L_ü[‚¨•™øj$}Ü”ˆ¯+KÀ70_ù~½`ˆH—~tùRï hŸ_8Ø$8šËj§ûëH+|£ÂÃAøbï£UUÜ•Ýȹ³®à¹YÌ5›#˜Vð>ÓJ~pÅDF¾uß1¶B#¯ÉnéyÆëƒ/Ç•¯yòŠz·¯‡~)«ÇœFSÝ "× ÖN+£Û8×9“hJCŠ‘pÑ…¡h±¥ùÔÕ!‹pá”HVš¦D„+úžég:…}$ s‚ÿžbøó-aB[%ð\DÁ- F—krÝÒßP/MF¨)  Lq‹czó£¿ËÈÐÎl…DwœÕ7:”@PÄ„¼¥ÕŽ^2ù“vœ¡—™g⌠ÏÈV|R° Y@¾Í@(¾îI<êzÙ5û¿çª´e –#™dkk”xÝüLèø½)Å$¾Vç>à)ËoÅQB;DÞ@‡-ÿÔFwüß Qò%öytR઱A›¯ó‹_´žÛ"™ŸÆÚ½^`saü0(Qûeç©^›Ë0gêÿÜ'¼z‡ãš?8ê1ÿ÷ÿT‹™Ñèû[HQM—)ö<îy­Å³ÛS(ÍÏDj@JLГϷ%Eù !Ãå&™J¸„[n1ìýÖûÍd§Ä5õV½¸„ŠvFƒõ9怩V›*y * ßr¶XÄ!±cƒ:Ä–Çóö-¿Ýqoüc&ÁB[J“<Ô'¿YÔ gdn~eåc^ݘè3EäVÓáø@ÝÛD>I—Ô_ìæ³„WZ—€ÁÖü܇9S(Ibð‡„¸9 ³â‡±ˆÕG›˜VœË=–Â2ŽåÿxÄ£ò»ûsƒžƒ½±¼Ò ýîâÁ{ŽùhèncqS[é2i±P7»‡ƒRÆÇ %áx½KGÍ4(˜ýv: å ­ü1\¦Â*+7‡Bþ…Pؾ¨Çñ†¦é{þ#ªq¿+ûýUı„Œí”d¦0p¼¤4*74ù}”˜Û_uã§gGýÅy–nq*7ge0uŠ”fX‘q7@¡˜øÌ¯0oŒwófúmì'\A?Àœ¼R‰ÚNrc?*¹iï¨,âÍÖl·Ò~ôMÍ^G þòB““˜,"¾c¾?ˆÆiÂë ;s2EˆY¯üèe qDA"\Cæ]Ïý‹«›bí'É·¤ã¿ñ$¶liœ}åü¿^cö-²^mýïKç«70¯s@Y‰ Õ–Å·àRZžQ¯W©œ4y–Òb§Í+¡SŠˆ[€@ÂçÁIç$7û´‰äÐÁº~4ðUhn1õ’ÝâØºÊ&³pLùãߊ7Îꌇ)|¡Èb˜¢…­l‰‹<•i¬oA¶›˜÷](ƒ“3ÐYát895 æúcMÁâp\{Ç,²u¨jIZB¯·ÌF&˜Ò8ç™ Ðéàf3Ù-ñ­”&a˜¼àP4Ðÿ¨Ž[Ñܸ¤˜ì@e5Úp›žNU‡šîþJ³|ߨt*¤´Èå lGú¨/)±{)Ö&ÅÓ^>‹Ñ}Ôôãmm\vªJ}Ýí)ÌqêJ0ØxÌO0*<ö´µºä©¿'À °Á)’—ªéÀ4*ýÄÀÇÌ⃹&¤ÀT·dÀfêÿg.5ñžÉÉtß|X×úmOha©T;Nït˜E=fô¯ì÷; …0ÇÊjSœHÔc¾lVú`Aá&´[äžJ)µà7¾ŽÕÔ0óÂ,põlgaššøoO53†×8¼IXב¡}>¢ ¨SÚÁ*´­F´FÞõU»ªÚ¦ï„¡iU H­æ7ËfAâ_Ìkf¯™ýW5¸êQqy‰N°u"åAu´¢Ý;ÒIDi Ô>•pU,üFFðsfJï6‰˜W„¾IÞ·[ÀµÊ¡YÿNv¾¤8G=϶¥9‘@Ô)£]°hÈbñö¨e¸¤.Æ~õ´½‘•úÇ ²d%ß3Xd5ò”RõfY;ôå–¨-!BO1!ÿ‘9¬OJ©MFM{I.¹!O‹…?´Z¤”¶û^¼ uJÑQ¯l$P—!{>Jáôs›ÿŠÀí`ÜAé ä¿ #¹P¤xíKnwƒ”É!ÂÁìr)Ö±˜$k˜(ÆÑÜ]"l¥©ŒÁAPV–hþCÈ ,Ø$²‚kˆdøÛ#Ihy hä'™xƒã{#ó”úÆn5ñ¢ œBK¾=v–<ÐF­ mFÈÍFµåšÏ¾= ­4øã8ìQ}KµŠ‰ÀÍFŽsYAsº5Ukw‚àýã(ëajìM˜Ø#‡i=wy>cÒ™ìDZA¸’X—v¨Ó&ìðñ3ŒbÑûFjT²ø2'ºôux·û¥â$ýa Wš¿MÁijt ACöþÚHv#üÆó¡›TAsŽ`ÒÒem©=û­[R²‡Ü¡L›%¿èòäB:¢^ñR9Ž˜Q§‰e¶k¹š­-–ÞÆÈ?†ÒvüÒqÇk{—ë†Ú„:/£®+U\=Ü?*€9 DJîUò˜«­|§’;ûC‰²µ±“;Ç3-¥¤2C$¾E¬ÈÉŒxZ–/ "h¡ îb!‰T^Ÿ ¹”‡hk5>Xåc³–L^ÅjP¾¬g;’< lxp,@ªªʶÏé#-b¿Ô» Z¿¹5X'ýþüÖjDèb„¤I-¡ªƒ«óvS®éêym# )øø$ñ“Y†•×ÂBº&W#µâQ¾› I|)?À‚°uÿÓcßpqÓ.ÞBóÑCY;û–šÿµuÑ¢“ÔÞƒM¨€®|sç‚óã—IûÙ¾|CN³Û‚«­Bƒ^Œÿ'cÿ‘â? ‚S_Jƈ”{(”ªíH e²¡ÜÊ‹‰›¶£¤§QswKB™~œõÓå%·F¼÷2PH‹Ch,#—ká•„rE€rùadóxÐÈéRì‡ÏºÊozŒ ßëYd‰ÌŠí¢5ñÄ “ùo­1à­ª_“uQ· “‡p8)Eg0ÑÁ€äè©Ã…4ן#ÏxÖ-ß^‚ÖÖæb³oÇ"©ôû‚­+øêbuáÄûw·•ýéd^ü¼C¯:¢‚¢®~š½0ßuDú iUÏFWþŠ, š÷§k NÒ3é©ä 9åÁú¹ÐFHƒ«¯K]í ‰ë-ˆ¢0Ñ“u°\9™·×>#Gs+5³Xiþ>ý8ôɵäÎBcsº¥}kûu&ƒç„3¶â”õѦ‚"Mš5L, ¨À´[RY>¤ô§^ž2À}È5c®-Ù¥8Y¬€‹Wp:&ò©I•ù›f…jè˜ PŽølžËÂ`Ì:x/xõðç¦YÀ†s ë¾¥‰¥>rj‰9î#~ eHÚ[Q›àLöÛÚÍÄÄ~(±3+ˆ°ˬD{çÙgàª!]·im<ó6=p´[«á%¦°Ùä¬ ïü£Æ£ÅòpâúöÓjPÿÁÏ5MÛTIýîë9íø_ÝÄÿKhز0AǸ½Ìót0ož¼eY§1Eä|~s~èÑ7Iw66úÕ)ý·lÉë’»!!˜¿·½:N@¸²š:À:Óu°d¢ñBåŒ&( ƒ¨: 2ÌPŸ¦GÄss‰ÛaÓ~ú¬kVô¬Df)dç›gì`VÞÞærð!—€†¨¤½—±“î©]¸BWÔÝ{<-O»¤¢ú¢€´¯’‰¨!”¹$Iã÷ ÌáÙ‚ÿg(·,5üÖù‰¬3=(\ !%Œ¥Qz»Ó(‹?q_‡¥½ y·Q5ɦԡ]¯‹¸·s´ÆÙ üt®<¢=I~f u¢TæÂîðéÂU8û°ìàêúÎß~\説?dÓ†›H³áîgUUtEíï§?_ø>ÃL‘F‹Š¸Kdœç ›#†.ŸÆZ‚D®R¯á>^ˆ‹'}dT=^ñx¥s×Î9Á<²qDÕ[híÍg.u~O€uŒ:]Ìh–àÚä\ÅŹ}6­¾Dj” 'ª’ÆÃ”uäa¶Çý|Ze)ˆgÔ‘:H¢›ö¬±{ ”'2îçq‚Û¡·øÞt:xdc#Ѭlýª£º È_é¹Ü¿h½!Åo?ùÛBhÉÑìsyR`ïN j†¹›Î6Ñj‰ËÌ=)ÁÍØcºÎ³LH1~, íÖί¼èìnr¤>rœ©9a\ñ–½O¥øÀe;έV.gãtçô1p™äTƒ¡Ÿ‘ÍPekmY D^ˆ>U"²±±sȎ׀–@eê‘ ›ýv«† ¸u÷àzˆqåÝñ0 »L×pâÓ‚yO9ξà®Eê©+±TP•¿;NyÔ¢JÓm©NúW\°ÊOFÊg‘ °ÊüÈÑkg¥>#!SŸþ¨š³¡ÒAá_íÒl]ÜÀJž­,:—èÛ[ÜDåµNɦJeÙ{îÔ7•ÔëR¸æ˜@{DŹ™¼ŠZ2¯…%ÓdB¼óÇ[[ eŠ–~9Ê1t¨âDñ(otÝR))¸ó9 b"tÿrö[ay?~Ζ‚ó’13€$z÷…ªlõ^ÖXÒÌAë)é8ÍO1rˆê칕št½(=“Ù¶+àÛ;À ê10Th\„M\%’„3 Pc(š&*¢¼¹k ¥¬zÂmŸ¢ ÞÐè'8ÿFÑ¡9h‚èæp¸ÜBMêB…!Ð~¨ÄNæ Ôr¼{GÈ™¥>åÒŒE¶fyw¦‡ƒ@-§ÆV“«ç?Tªˆ·:-,·ß"k/†äjµP ¶ã~„VäqŒ~ÄæZ26â>”ƒ‘}¸)%̵w‡ Œ•@¡d¡ÿÛeQ–-Å™†óÙ­ùJÄv‹öNí}Çß'cH{QW(9+Ü:ÏLj½¨×8Xiýš‡Ezí‘ÂÃJMcéÉÌò3­ä¶Ëýú° âÆ o‚ Ó8¬q.V;­òŸ< „ó’’t%9ßç3ÞÏ`í‚MC®T3 5'þ™w'nMƒùwnP+Š?Íû[þÖ"Õ#pÙõLJ7K{ò`€•œ }º” —,b©¡ ‰‘ ȃÊqP-Pûˆ*©Ë;†“Nl31SÚ±ŸíGŸ`¤¾•0ÀÌXb¼Àj\×ð›ŽT‘ÇäFŽÝã2Ãi‹á±ŽzJE~âTwäÃ-2÷­/`*~²€’ãÁTF 2«>¡˜ƒ5¤¸•öÇV5û56C…uåqµõ¼“¡œ×Ýê"k-ù¦Q© ¶Ò¤ÕsL>~ÿ=¦2MEM[c MGEâcë5°¾Þ‘ØÌl%9ÀÏ_­µÊû!5çDÓ'ð¤ÏrÓ;WYÐiªíðhCé)¾}ÎÛ|œªò7Ùq-fIÜT)¼†O¿˜©ÁPÖ goqÇâL/òϘbSØ|¸ZünÁˆÐXÿ™É‰¥éðŒN$Ô„$1înC1ñSξø¨®NOP8†,£Ä…¹dwÕPÓ 纳3|Âf¬B+´kk•,œÍ– ž·GË •£ô\7ott2Çž*è¾8ÜäÕÏbõµA¶”3öÅÂ娦=[ÁBÄ·¸kRx¢kÏËç«5V6â²aaò\É"kve> N Ⱥв‹ –µ7ÿwöyä)ÔÎ:ñMWmüooò®G«Ó$ªÛË[Z!›fi"Üð"Œ}¥Ç5†¯‚zI‹_´žÛ"™ŸÆö­‰>g  )kÚž½×E[ ôK~éy›ÞÛ9yo f–Ä'¥·g“¥y¢ûk=P Á"PÚ„Ð>¨e|±üŠ ¡"½}«®_ô³5èÔyÆŽÝkÆsƒ ¼ÞTô±3¥ˆ¨ô*ñ¬”« fË_ž;ŠŸg7}?ØõÛV€3°VƒþxçÌ1'¦ôXÙ,ùtZa[ìŒO¤§ÉŠÚä%¿ï•PLÄÒJìÎÏͬÊ' óÜøjÞ(½Ø§–™\ÜÙ”‹wžò¢¹Ï*^Ãà|­ 5÷¯ iGÎZ­€Ê 0D™Qê!/ILÊ?9|c€Wñ¾È-?;®â¥áS ¸Ø“¥þ¤$µ<Í1m’íXØÂ›¥×¿\9’ zqå÷ï­Ì÷dóæâ°–ó&{ý{±yÂÞ‡£ÚÆ´aZÉÖ*…²]|äüxõÖÍÖép(§û3’Pz¸àfb½‘ ž·•¤ÔËDð³^ù~.ãÈo¾(˜ÔâÈ{\sö1têÜ ã9›Ï]Ä¡È>ÍEÝ8ðS’DÎvYTŒ Ž0I„«j¾?\Ôi7Ú¦çÃŽ\è†|÷ò4$ɪ’ö¼ rÊgA 9ãFÒY>ˆ bïî&·a#Ñêt#þatÓ—-„e¬¨Æ]d¡ü»R­Ò1"à ïT3e|“ü*8„a`7(ß%F–£½ÖÛšâóð­kc]l">ìÝðWò³´F‡¬cLäçäù´†oaÕ£\nÍ—á ÌYœ”Åîk‹Áß¹à BX:–¼*.6QÅ^™ Ñ\þj&.2µ²^ %«NAk|ý²Ž<ÅT»iNí»JB4fI뎨&›ò£7رÝJ6É€gb¹}T¶2îD²¸ÚÔE«“‚ùu_A½ WŸû:ðŸHؘ\†Š*–yžîÑ$Ÿ}Û,5Ý ãµ^ªÜ‡ÁÉsûˆ?7™|þ¾“u†ì'ÃDZŠyN&AlïíÑÍ—xÿqÓPr?öH$yÈlê2ü )Nštm”‘S¥dĦß"טºÞEVr<•ÉÇ}îXJ<šxøš"דªZ£Å-­àhç¦)õ_!ÔçQü›€§Y›åoLžvø°ZþÃÿàX*ÿ›ÝP0þ¦œžÈûÓðb ŸÞ_ÕFÜ`Xº6óÕö8ãÑçÿpü…‘E—«©ö¬±~ÌI¥‡E£}§«XHNÞÂ@šû_Hën=n=)x‰˜n¯ßùä?:xÆØYçgƒ®Æ|3EVj\€:¤§®,ûºÑ`32}Us­4²Ù'V\áÊú™ûR­ª©s„÷­Ò×I&”ÌðäZÇÉ †Â©jÓ­™“]?cÿK>W™üž†`iùOæ±Ç̨{9»Âá÷4@e¨LX0òX3ÎÊV»ÏÎ’Ø=®ÿÝAuìVtí^~Ô &Ž›cJåK‰IÀíB’°ßN6ªL2Ô['«59!ë.Gà»Ì¸r±C Q¿0„Äѽ …jÝ“ÔÅô•äh‰Uç›—¡>8LÄo¾Î¢´—ü„©²hDC4ï9G-/E ^«KkQWU³îAa‘؉¿yãHSù­›¸Ül‹tí´ Ê:|Ÿž^t`—ì˜x¥¶–eIéˆZ"ÿ:Â϶é Í{YIÃ]©5yØý^z ")Mž©Sɉ¤x˜á3³Ù’üm@§_ÄzszŠÐý­ŒnóÃIË@gØ|±Û½æZ áú/nÚàäªl]~o×BðÙc¶¯?²õõ®lˆ´Ä·žâeoO½–èa¤ âöeT^„‡Cï:…(tLUÖžOYúÕXÍSÜN%äQÒ‘YCñì‡ÅGn‰Âl9Ù„M`í ºò”Ê`~•5¼|dŠäB¹R#4ŸÑûF}9d%ÿ¥©¦bªá7®ÿ,ÐŽ©¿¯4ù¬5-¡Âêaã}0{uzgÿUCkæ4,ü Î …ÏäI¿äS‰ZHé¬öL Ìž¹ñ£5ø& ]â­‰PÿÎ{æ ’ûÊÇK K™j7Jô¬_~ÈøC­O…Ùà¾Ã‘Yí àUÖ¨ `‘$$ºóæÆeœy`˜ŠÐ˜73ó+¦Œ!?8Ò&o±l“^ðÂ¥ÙàýÛƒyÕa²!Š¡… }Ÿ§t–u‰7a%^ć ¸mŒf3(ƒ¾ µ<ÕÕØ¨5¤çJBÞ(ÈjÅ *¶·ZJf3ö§È¸>úŠ®þrJ3;mT,ÇLN0a)?‹ J»{#Õæj¹? 5€ÅÛϧ‘§ã*I?Áßæ[ èï¶zág» TèëŸ^³¬yn¢‹Ð§ñºîÊåÔýÖÏG,»:þ§EÓ\JW®‰–Ô—yѵ+©?›&®Ý*tg~6yˆEµ,žÑï{àÛ%½à‘Xë#‘uzR\ç «Gu¾Ó?ò£uþÏ_x²ŠA"ìê!N>J1¢º[7lúÛÁ«q»¡V½Õ­ÐEY 6¢i*!ŽÝWX_7twWÒNC³ËrðÐ)ˆµp÷ö3Ôƒ#Ÿ›×öh;õQÌ÷Zh†Ia"¡kúpÜ€¼üâÑ‚d@²zÅón£f'§¨ÕgÓ}¥•QT³8BÀò¬D5Ó{I¬þõÞݽÆã}+›v=š7ýÖùþàŒù¢X¦ÍØ+ˆ6SÓջ†­þÓé¡ÏÐÏrú¨j<+ }ÑŸ3 k´š’¦A£Óá›)lȸÇj$浚ýg&Aï\v Æ C"U ¹qNœ‹œd 0g†$¶QÏà‹.…ž» G;>x”ƒÆÖn=ìê.§9ý\·ÁÅ•IÏ„Ç<Ÿ/6 ˜}¶’Lh?á>3’~I·æýÿ…G8œás™$ÔŽþit@Ȭö$]4™–?ûžWÕ‘‚Û†bóhÔú.@·]DHØxs ™²æD§æ(âÙç£ç×v¸y3¡.¹·‰¨FG…Gä<®šZ’¯r‡X\¸Uí”/èý¢8_ ZMZU±øDSE‹|÷œnÿ&ÿê8*¸Â™Ãê½>̽îRo¶ItÀ÷;`T¿Â9†ù³È§K„šs1ŒÅ1røá$yÐ!V†IˆÂÖŠ’…Wó WËëÇiW2®ÊL߈rßAº—‡³‘xr?I½ãŠrI–ª¹»’uUÄ—ªôZв:6<«MààÄ¡m[ÄÀk­‚ß~G¼v/\œA¼É.t£Æ€àÆI ýxpdÖùtE?±£QlÝ…H ü õèÞT7Íarfz^6¸g©ð²jÁ]„"aÛPþ>W†rù·rQ•—.¶¿ÌV2A4Ëô'ªžkábÓF# w³àÕfÑeC” nOÅ·Œ¦>}ŠQ˜&áöÃÒu,üð':Zk÷x®. ìjæÞž×ÜçX‘vvÖ§oÅTGé¥6)­f`LÚñMæõ2†âßÝ“ù^vÞÌuÕ„+Û‹C¥ŸÏóÕïÓó;ýRFeS²hÈ=VbâÚ=ô{Ü%Ø|ûÍ}7[0+ÞÇwÆ }ZÕGD¦rÄÍ–[r^åbÒ™®.˜i™wÙ¡ícákVM@û^ÀÆÎ§ÖûÞEœ—Ñu io³w[íuåæÊªCëèå=4L×äÿ†÷œÔ[’Ïíèá=&ôsoú…É-éú!(d£eÌUÞšZUu^oƒÓ+¤G·/Ù\Ï[/ØZ.–µþ…ݬôœz*ñ̑ͨhÂí£Áʃ›ÁœÛÚ¶¤,N7Ï6"eÅ—xÐôÝÈF@fõ.ëø Lí×BH”ã^B<"rÕ„ŸØ÷¹…kÌf‚]ìôµ§»™Œ4-ëͤð¬áRcù݇HŠé}j´¤<¥’£áCa)‚¢Q!¦ä”ðµÍЕWwÌÒÉgoóÊ !N†q¢çVoUührªdïG6I`ôroÞªõ‰Ï¯³Ù!:»H >vÆ7´€ªÜ=TfÖð…öÿ 6>|…ð~¢æì£(í¬(“epEùOÀí*ž˜×èì'g÷¸vÂ,×nF’Þ‹Ç|»ÁXŒpîÚ9ázž †cÏŸµ@ö1ÇÒe³>%ªñµWÈá^è¿"ä[GÛBð¨ñ–nŸÈ«’õ@~òœ«/~(Cè1SímíW•Ç퇧…ZNòúå!ñ¾\|%(òãâ*&[l"ù˽1Åcê´¶XLu×¹v«]Bº·ÉPÊÿYì¸ÊÝÂg:c%Çwá«=Ëi›:Œ uM Ï÷R,7ù0³î=úÕIñH²ü`ô/±Ã.n_¬jÖ}!¾üS³ÀÀ8¢îí¡pi5HçËÌí8;¹`å\Yòƒìásù[Dö»ãü[(ˆ˜lž·Ñœ­ZbZ¦síÑR›ŠÏü–Öê–€ëßþÆ$¶ê‚‡Ú´9;@ÐÚ¬‰¾"l`ì#Æ‘Áb æ6Ít¥PZ?½,qPŸ6·®Ûøx4{ÿ6ùÌi*£2ÊZñµUïûeµ4a´À—º½,åó‰¾úû ›öÈþÓŒ¦pè†À]7Á-AX¦‰Øö¨¸!Ò—Xx;Ëå| /¢Ág¶úêh¨è~á˜$VOûÙAü^¯k$ÿéÀ}›–ñü$°Œo}rø¦ïÚâÓ›ÙjGwV‘~´:¦ œþ1¢'ñ;Z$”Î}ÊŸ_c¿ÚSöKØígû‹|£U’cgX}–íE“HR!OòšB;»€Ò$ÞËíHÝ¥*Ùª„Ø›¨ÆŒb)¤õÔÛöo펉¿iˆâí?NŸÒÇ?uNÍÁí/tR®é.`͸Ÿ·fg¯ |š»ù¤ÚÀCñ@Þön´H’ÍhÖÅhvi÷T¥8zù»õ,ÐbÔ:D:ïÕå¥èܲóδÓê˧vÄ’c§J9Õ‡(ñ9ñ؟lj¾[’Ò/DpÕ¼ü¿ã€ypµívKu“V©È£Â‰ñû[{uôV DT(aš©y«¡L†Î‡s/˸RÜ’ê Ví"ÇmT< Å"÷ü¶X2¸„[ªûªs ë]1ú¿›J;ç‚RJÕ0­W­¶1‰Â€Ë·uÖCŸÏÜË\þ$íöó¬5¢X¼1oá/î†R)äÛw ÿ0–îŽç_ºí³^ ;˜¾ƒÿÎa<–N¬`~‘m®ûXTžþ㔩Ü#_ŵºCtƒÉÖz)´øô*ÝŽZP/Þ¬F™‚¤#˜ðíËú®ù¢KÁPÞF*MvÄë†I»2q8k‘Ö¡SÊÎ%Ö™†yJxRº6x(ÚÐ'ª'D¯slðå+*þŽ{kFiª÷ËT)qß ü,c[Ò‰îß_§cØëú"¬‘½Ô}]ËúþDp¸^4ï6;«¡ÄaÍŽ^’Än¦[¦ ‘¥ƒÝÄŒZ¼3ǃ–ÆØê‘“e A´6,ƒ._18:ûx+ä«/·Z+ò3ÎÔ!ßùÔA½¢22ÖµE-Ýê꿼q¨Ø "¸î±–7«ÖÁÙ$låÇœñ_TÅ…ú’c´–°ßçÖ¿!ÖI HÕ›íL–T>Ï„*}‡g dÏ‚dáWà޾РŠJM€UŸ­áêݶ²ö+¦’çƒw£EÈ\߯ÁÒù˜A v·CTå÷Ñ.Ÿö\*C¡šÁIá0ˆ3µ¶ÛÔ¹v&²û;³'ìA9wêD'ôzI 8`‰ŒÂÍWÁ?küŸq\'j…ý?Hm&6›-+â¿gˆnpžÑŒk¬Ùwl\d“äÚÙ7,¹êÇ1ÄG }7!?#¢?‚·™Ð÷xÌ×ÊxcBñä9Ú“ô˜g/¾½Ê5Ö¡¹›#Ýtv¡!à:Ïü¬0æØ¥=­5O4ÐÃ\dPL¥« 95°*€ZG{ì’´ÀéT€¾óãpì¯ê"¢D<}êþÛ²€×9̶mä~$¦´G9Óüña™zã ãJÁÂsf,å_yÊLr [ n’³ÙwÝ:Þcè_‚ª¤E«ak‚»IÓ u¾¶"Yv¿¿«–ÉrN0ì«6Ñf ±Æÿ V6°ñj¬JhOîÚè/7ø:/}sqºeÿ·Ø¹ê‘b¯Øò8ß‹²QD1OAŠ¢‹ð›?Òç&fÎ.…ÅI>‡râCg:öb²LþE$òv}|w3-¹›Ð¯ªN·Ç¸Ðàóÿî²qZ†®ãâÝÍ“µOýe¥öÇÉKº’«¯Kí/-q#InÝç>DÜ™{Ç/=…& ò¡bYÕdúßÉ?Ýf¨‡eTÀèöï»FKf”`-ÿƒÀ´w_™ž·–ðAéÍ)4P$oW¯(Ã6ô Êsa1êz—€ @*á߯~ÎoëÕ;}¥ÊT„©ãNÿÖ&Wõ êvw:œçJÔøùî1‹Ðô‘Ú,ì}RžA ÷ð6!w¥?3èÐ}¢¥d¯g7+ì´æ«å!ÒŒ AE²ÛÛÀ»Sd‰qXH‘GèHÛmSÞ¡v8U‚áKœïÙ[úû¦!‚GÃÊÍ™¡S´ótpœ»7 ¶Sk l&ót ù3W[« Ìé Wˆ~¤¬^"öEJkÜL£„#ßb,¸þÚo· ©5¢{Ž_®»Þ…`¥Ì.’.åd¬ŸoÊn$§s «“$ß÷ß3ʉ)<óî{s™L’Á—$\ãx¼âÂÏ0úQB¹™(WS¶ú€šMsBû*hƒö÷òÒãý(’šfEü/ÍL©˜„øKþ]úe×vxâÂ¥ôs † °a‘Gs]×·×gü>YÞîµC¾ä]µå y± ¶}`Q²ˆ>ã1<#Í|ž}63,û©Ø Nk©†_½=ì '§¤%¬/©qç›'•@àÙ,+FÁžœï|žÔz[lRXSåÄñï,üš¯Y£Dë¬/)‘!tÑIDšÛWs‰‡ö`{.4-A³)ŽÅâ|,W±lª)Ø ïp?åý~R‰˜aŽih¥lά§ÕÒ ¹±y]ƒs&8VUëdÇ­ÃÙ.©Ö€m ” X–nuØn× –B(Õï$ÆÏÝÓ'`ûZê£Ê0½ýV[€ý‚Ìî´ZZ¥§Ø=O²½Á©{Ü7ê+Â]T.¢3†ÑÄnáÙzâéõï ­Hs“{Mˆ³¡A! ]Ûß‘ g±ñšµ›9Ÿù³ô-ÁëÕ¹N{žáPC]X˜ƒØ:È (Ÿ)X“˜²B0wËE«~Öžgá’mÿ©<'ÝUÒ.v‘®òä>…þ…¦O©;¬í$9VõF“<(2µEnÉ„!ž YÓ^B´™ v—j©Õ´zå‡î"]%lŸD8õ…LæP©ïOýfa¡ƒN&ùYÊðo‹¨)zè¼ÌØÙ•&£Û­Â:vȲÔR6úŸˆC ÞN¹o†i\ɼ®6V8ÕÆs—x©ñÉ]œÇ^Õ‹»éxí–‚,GO ø¥!ùìfí¤^™ð¢&.C8@pØÌ7jE]"ºƒBX2ô,ìñ‡÷q+lå-\Bí-tD¥‡ÿGCf@ SAJx–QÀüRú³I{üJZŒ¸…Tž3ZíÖRaJ<À»’=¥rö7ΖÍX®¤î²66wRÌVú((QAû<ó”$ H…MŽÌä˜Ç¯1¹Î|…]Ï“Hueê‘vyo;.þê0 9Ý0|[ §T0HÙ¿ªMúÖ.éé‡(sñÝßu•ÕÝÐ*:Ë$”ߺbçÀê0Nx̯UO–ÄcÆRS´‡é[ A×(Ðü”àÌÈfñx¶Á]0¾í‚ãs÷?ð»l½0}×Ì¥@oËTØz×ú¼mº*q0“F ² F9•ÈÏ’’*-_ÊæÂˆØÇ|g+íUgƒ’¤õ^øÕ ìÚÕêPH¦AİaϵxívØ›œÝ ®öÅœ‹›¦ Ùî- Gão“W»8L7ǃYòÐÛº ºrÈi‡©ÈŽ­¶º’5è }‚°|0O´Ÿ"-ÿ𻌛ÎzÖäõë°RÁôO®¹ˆ%\PáÜ–îÿòv”r€èòÈ-Ëjÿ/à¦9甞Ÿ¡wV>îî|G/![åF%ÅŽC$Õ_JW{GóBÑ KÚ6!U¹¥+m›/Q ÔÉxÉJüs$å½í°·Ø·OP# B}e6’f…ð7±Ø±åt?Êw,‰{uñç„è±ÉaoÔÁL#Ùô8ZáðLÎYþ¢ ë;_ÕØ˜ ¦d ÷ÞÒq0·`“×K|wð†XŽ4ÑZP%¢ï—4áû^  ŠQR?{Ø,ý®™§ È¢D•ÇײÔs#n¤»Á4, »jŸvu]M5èÕñ¦_+\|gߟöŠb$¯Á¬ ?èÑAJ¿D%”ÎÃ? ”‹bEzÀv Ñ3}“V´‹øó­U µÙí’ ®¸·5Â'r‰€Øtnr:8ü·û¦:ÄEºgþÅ/XßÎ-ZGé`ìGX;0Å–êÄ¢ž }aÙA¸çÝ„RK@èd¼˜Aë…«ÁA›Ìœ?ødÔ¦üuF78™²ý‡rãø‰ß¨™Q™s“ß}DµNÒCc4.£<ùî;—Søhm8™ýåö°„€3ÚßNfAægNY © "ÿÝKZî;ùº·Qy?2–mA¤”؇³íÎYè÷e²Ç&¬-ã!;s*ÌrÑ®œö‘.¸h'º [a¶®Vb>œdKðåÈíý½ª8;éVeÆZŠP:‡ ÈäcHO¤¼§úÁÂëy„ÒöiGslá=†yЀÖvIK µôgÊ ‘,F]É¥µr EÞûWœ°“Æ*†‘»@’ȸÍ<½¬K¯ºª¼Æ™J^'«‘W»Æ‰”ŸÔnm(Dp„å,ׇÀÖJ„-=ášîRþ>rÐqÝ# ‹á-Ä€£$f™¦ãŽ7$âQ¹Ê×+çŒüäéí²€Ò @Ž1u—ËWtáµ! ð2^bŽö'VAøé‚?õ§Wx±~¬¹QÊ~&½Á^5†1 Ú C,éaÕïGNfU;²JVXÙ–Iïu „½Í,Ki­ùß‘Æ ;W¿ú†íÌy;Û`J¨ êÚoŽ:ÒÒGÐÆYFŒ˜3®ºV:]2•!MÓ9+ÚTÕlûhÍPAT…(æhMœ¡j""i&º¨¨Y4Ž e¢ÿíÙû^'°ç:¼+èéŒR,²Ví2bhñ }³L˜~ä·#ñ%çR¯äÊøîPáˆ<ž;ýЈËÄYoº$¨CÞx{زëèÑ •‘_±&Qe‹ŒFƒü¿&1"Щõ§×+CMEÛUh^Hª²JX/·jÅèGLÓû8Ÿr*”­Ø¤LVž}×Îaµižy$P)*‚éUf©ö)AD~‚r ?$_B}|ò±©/ÙDý(kŽõã:N»E`wo}iõ”Eñ»Û»ü(5ØÖ1ñN^Ã$ • KP>TM?;¾‘ MGÙŒŽ.%›óÝ™÷$é¼~•‚c¨zj@†þ€KIJäj¾Ñ–žS0FÓfìÐvŸfýª¼wøÎâÞ3…ÓœèøzxKë)Mgó*혜±¦ wG¶³f<Ašôq-im•íŸÜlK4 fõ&ävdAö'´ŸQS‹0Ã2Í ^ñÊ1Ãi•vŠÐ?ûLª"nØÞľ±K©cØNè´¥à†÷Û©’ˆJµëåÍŒ:ª$AšÍ«]ñy^‹5k¨î×2R¸“µÊqû©ž\’_Ù¤>Tì_"‹½ù'›û*^ŸíåYÎLGMô,Yâæúí÷a‚#sbÊÅÍ@ª…ØQÖ6¶>ëi)c¤­u¸HˆXØSýËLÝ-eîðY“NÂ\¿§Qú%íAnèOÄŠ†4u8êro€uôLŽ!8>šà€!Ê s›úã§Žr½6|± ËÝy¡žj&þçd­Ðó1+ _Yß4œV>ëú>ðï]„:qžÒX!?ÍçXÍd$@`/\ú5GTWMyýF):º"Mt09Ï2)”\å“/¶¼oÀË©û‚7F+wÉú„sï>¿_ÑÍÜÿÚxqJ`lZµ×VòÞx™ºmVÁ[öâk´†½îU<ë~†q7yæI~Èfº úºŸÀÍ”5”ˆUßÀT£K‹±fmnÄÖ•R°§|@ú–æyÁüü‰à°§Ìé1ǦßllcÇ!ùþç¹jíC{¢<–?è4ØUe!çóöÍõÜà  å¿#´¸/õHœõ¥¢õñ¹0²ÌVú²ÓL£Pr äúçqã1^èÂS¶oM¯£cl=‚—+±µÕÕ&›û‚•–-P]sÂm;'uÖæ$óÈ.ú½f÷ñ‚U—™/’kR [>\EÒûÂíÉá•Yh¶wú÷ÛþøqŽtPAlG-ÑÖ=Ô æFæï9k\až¾š]³„äù ¿ë kE{D 2« h‡\J ?tDÅ X0ì#ýü7‚Økqè¤<„g&Å%§à“ân'`Àÿ[{ø endstream endobj 34 0 obj 66940 endobj 35 0 obj <> endobj 36 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡GÎt‘øˆ’®>R4éuw¿¿Ï·õ?ÓåøoÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·ÊãésM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§mܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒßè·RŸ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßátF8#ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;ÑÈDt8. Pi|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-AÍÄNèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8eÁM‹³<—“#artË„F{ÇN‡® tÛáÞ®Lˆvqè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿdØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 37 0 obj <> endobj 38 0 obj <> endobj 39 0 obj <> endobj 1 0 obj <>/Contents 2 0 R>> endobj 4 0 obj <>/Contents 5 0 R>> endobj 7 0 obj <>/Contents 8 0 R>> endobj 10 0 obj <>/Contents 11 0 R>> endobj 13 0 obj <>/Contents 14 0 R>> endobj 16 0 obj <>/Contents 17 0 R>> endobj 19 0 obj <>/Contents 20 0 R>> endobj 22 0 obj <> endobj 40 0 obj <> endobj 41 0 obj < /Producer /CreationDate(D:20110130132755+01'00')>> endobj xref 0 42 0000000000 65535 f 0000263578 00000 n 0000000019 00000 n 0000000784 00000 n 0000263722 00000 n 0000000804 00000 n 0000002013 00000 n 0000263866 00000 n 0000002034 00000 n 0000003463 00000 n 0000264010 00000 n 0000003484 00000 n 0000005163 00000 n 0000264156 00000 n 0000005185 00000 n 0000006979 00000 n 0000264302 00000 n 0000007001 00000 n 0000009045 00000 n 0000264448 00000 n 0000009067 00000 n 0000011098 00000 n 0000264594 00000 n 0000011120 00000 n 0000111694 00000 n 0000111718 00000 n 0000111909 00000 n 0000112854 00000 n 0000113819 00000 n 0000192163 00000 n 0000192186 00000 n 0000192374 00000 n 0000193319 00000 n 0000194284 00000 n 0000261338 00000 n 0000261361 00000 n 0000261556 00000 n 0000262501 00000 n 0000263470 00000 n 0000263523 00000 n 0000264734 00000 n 0000264819 00000 n trailer <
<6F03F71E2C0CBECA6EB87A3334542145> ] /DocChecksum /5489B167EB40E05EF34B23982DB768B2 >> startxref 265010 %%EOF bobcat-3.19.01/processdata/0000755000175000017500000000000012257522663014425 5ustar frankfrankbobcat-3.19.01/processdata/processdata.decl0000644000175000017500000000113212257522663017563 0ustar frankfrank#ifndef INCLUDED_PROCESSDATA_DECL_ #define INCLUDED_PROCESSDATA_DECL_ #include #include #include #include "../signal/signal" #include "../processenums/processenums" namespace FBB { struct ProcessData: private ProcessEnums, public SignalHandler { std::thread d_limit; volatile ChildAction d_action = CHILD_ENDED; std::mutex d_mutex; std::condition_variable d_condition; size_t d_bufSize; ProcessData(size_t bufSize); ~ProcessData() override; private: void signalHandler(size_t signum) override; }; } // FBB #endif bobcat-3.19.01/processdata/destructor.cc0000644000175000017500000000015412257522663017132 0ustar frankfrank#include "processdata.ih" ProcessData::~ProcessData() { Signal::instance().remove(SIGCHLD, *this); } bobcat-3.19.01/processdata/processdata1.cc0000644000175000017500000000024112257522663017322 0ustar frankfrank#include "processdata.ih" ProcessData::ProcessData(size_t bufSize) : d_bufSize(bufSize == 0 ? 1 : bufSize) { Signal::instance().add(SIGCHLD, *this); } bobcat-3.19.01/processdata/processdata.ih0000644000175000017500000000050012257522663017252 0ustar frankfrank#include "processdata.decl" //#include // TMP //#include //#include //#include // //#include //#include // //#include "../exception/exception" //#include "../redirector/redirector" using namespace std; using namespace FBB; // #include "retpid1.f" bobcat-3.19.01/processdata/signalhandler.cc0000644000175000017500000000027412257522663017552 0ustar frankfrank#include "processdata.ih" void ProcessData::signalHandler(size_t signal) { if (d_action == TIME_LIMIT) { d_action = CHILD_ENDED; d_condition.notify_one(); } } bobcat-3.19.01/processenums/0000755000175000017500000000000012257522663014643 5ustar frankfrankbobcat-3.19.01/processenums/processenums0000644000175000017500000000704412257522663017321 0ustar frankfrank#ifndef INCLUDED_BOBCAT_PROCESSENUMS_ #define INCLUDED_BOBCAT_PROCESSENUMS_ namespace FBB { struct ProcessEnums { enum ChildOutput { NOTHING_AVAILABLE = 0, CHILD_COUT = 1 << 0, CHILD_CERR = 1 << 1, }; enum IOMode: size_t { NONE = 0, // no piping/redirection STD = NONE, // for backward compatibility reasons CIN = 1 << 0, COUT = 1 << 1, CERR = 1 << 2, ALL = CIN | COUT | CERR, IGNORE_COUT = 1 << 3, IGNORE_CERR = 1 << 4, IGNORE_COUT_CERR = IGNORE_COUT | IGNORE_CERR, MERGE_COUT_CERR = 1 << 5, DIRECT = 1 << 8, }; protected: static IOMode iomode(size_t mode); enum IOModeExt { ALL_IOMODES = (1 << 9) - 1, IN_PIPE = 1 << 10, OUT_PIPE = 1 << 11, CLOSE_ON_EXEC = 1 << 12, PIPES_OK = 1 << 13 }; friend IOMode operator|(IOMode lhs, IOModeExt rhs); friend IOMode operator|(IOModeExt lhs, IOModeExt rhs); friend IOMode &operator|=(IOMode &lhs, IOModeExt rhs); enum ChildAction { TIME_LIMIT, CHILD_ENDED }; }; inline ProcessEnums::ChildOutput operator|(ProcessEnums::ChildOutput lhs, ProcessEnums::ChildOutput rhs) { return static_cast( static_cast(lhs) | static_cast(rhs)); } inline bool operator&(ProcessEnums::ChildOutput lhs, ProcessEnums::ChildOutput rhs) { return static_cast(lhs) & static_cast(rhs); } inline ProcessEnums::IOMode ProcessEnums::iomode(size_t mode) { return static_cast(mode & ALL_IOMODES); } inline ProcessEnums::IOMode operator|(ProcessEnums::IOMode lhs, ProcessEnums::IOMode rhs) { return static_cast( static_cast(lhs) | static_cast(rhs)); } inline ProcessEnums::IOMode operator|(ProcessEnums::IOMode lhs, ProcessEnums::IOModeExt rhs) { return static_cast( static_cast(lhs) | static_cast(rhs)); } inline ProcessEnums::IOMode operator|(ProcessEnums::IOModeExt lhs, ProcessEnums::IOModeExt rhs) { return static_cast( static_cast(lhs) | static_cast(rhs)); } inline ProcessEnums::IOMode operator&(ProcessEnums::IOMode lhs, ProcessEnums::IOMode rhs) { return static_cast( static_cast(lhs) & static_cast(rhs)); } inline ProcessEnums::IOMode operator~(ProcessEnums::IOMode mode) { return static_cast(~static_cast(mode)); } inline ProcessEnums::IOMode &operator|=(ProcessEnums::IOMode &lhs, ProcessEnums::IOMode rhs) { reinterpret_cast(lhs) |= static_cast(rhs); return lhs; } inline ProcessEnums::IOMode &operator|=(ProcessEnums::IOMode &lhs, ProcessEnums::IOModeExt rhs) { reinterpret_cast(lhs) |= static_cast(rhs); return lhs; } } // FBB #endif bobcat-3.19.01/ptriter/0000755000175000017500000000000012223555274013603 5ustar frankfrankbobcat-3.19.01/ptriter/ptriter.f0000644000175000017500000000016412223554756015450 0ustar frankfranktemplate PtrIter ptrIter(Iterator const &iter) { return PtrIter(iter); } bobcat-3.19.01/ptriter/opstar.f0000644000175000017500000000017712223555052015261 0ustar frankfranktemplate typename PtrIter::PtrType PtrIter::operator*() const { return &*d_iter; } bobcat-3.19.01/ptriter/driver/0000755000175000017500000000000012222576540015074 5ustar frankfrankbobcat-3.19.01/ptriter/driver/driver.cc0000644000175000017500000000217012222576540016676 0ustar frankfrank#include #include #include #include #include #include using namespace std; using namespace FBB; int main() { cout << "Enter lines, the first word will be the map's key; " "^D when done.\n"; string key; string line; unordered_map map; while (cin >> key && getline(cin, line)) // fill the map map[key] = line; cout << '\n'; // initialize a support vector // vector, using ptrIter support(ptrIter(map.begin()), ptrIter(map.end())); // sort 'support' typedef unordered_map::value_type VT; sort(support.begin(), support.end(), [&](VT const *p1, VT const *p2) { return strcasecmp(p1->first.c_str(), p2->first.c_str()) < 0; } ); for(auto &element: support) // display sorted by key cout << element->first << ' ' << element->second << '\n'; } bobcat-3.19.01/ptriter/opeq.f0000644000175000017500000000020312223555214014703 0ustar frankfranktemplate bool PtrIter::operator==(PtrIter const &other) const { return d_iter == other.d_iter; } bobcat-3.19.01/ptriter/opneq.f0000644000175000017500000000020312223555256015067 0ustar frankfranktemplate bool PtrIter::operator!=(PtrIter const &other) const { return d_iter != other.d_iter; } bobcat-3.19.01/ptriter/ptriter1.f0000644000175000017500000000014412223555027015517 0ustar frankfranktemplate PtrIter::PtrIter(Iterator const &iter) : d_iter(iter) {} bobcat-3.19.01/ptriter/opinc.f0000644000175000017500000000016412223555162015057 0ustar frankfranktemplate PtrIter &PtrIter::operator++() { ++d_iter; return *this; } bobcat-3.19.01/ptriter/ptriter0000644000175000017500000000177612223555274015232 0ustar frankfrank#ifndef INCLUDED_BOBCAT_PTRITER_ #define INCLUDED_BOBCAT_PTRITER_ #include namespace FBB { template class PtrIter: public std::iterator { Iterator d_iter; public: typedef decltype(&*Iterator()) PtrType; PtrIter(Iterator const &iter); // 1.f PtrIter(PtrIter &&tmp) = default; PtrIter(PtrIter const &other) = default; PtrType operator*() const; // opstar.f PtrIter &operator++(); // opinc.f bool operator==(PtrIter const &other) const; // opeq.f bool operator!=(PtrIter const &other) const; // opneq.f }; #include "ptriter1.f" #include "opeq.f" #include "opinc.f" #include "opneq.f" #include "opstar.f" // Free functions #include "ptriter.f" } // FBB #endif bobcat-3.19.01/randbuffer/0000755000175000017500000000000012257325714014231 5ustar frankfrankbobcat-3.19.01/randbuffer/underflow.cc0000644000175000017500000000060212222576540016540 0ustar frankfrank#include "randbuffer.ih" int Randbuffer::underflow() { ostringstream ostr; ostr << d_min + static_cast((d_max - d_min) * (rand() / (RAND_MAX + 1.0))) << " "; size_t n = ostr.str().length(); char *cp = new char[n]; d_buffer.reset(cp); ostr.str().copy(cp, string::npos); setg(cp, cp, cp + n); return *gptr(); } bobcat-3.19.01/randbuffer/randbuffer.cc0000644000175000017500000000042012222576540016647 0ustar frankfrank#include "randbuffer.ih" Randbuffer::Randbuffer(int min, int max, size_t seed) { if (min <= max) { d_min = min; d_max = max; } else { d_min = max; d_max = min; } d_max++; srand(seed); setg(0, 0, 0); } bobcat-3.19.01/randbuffer/randbuffer.ih0000644000175000017500000000022112222576540016661 0ustar frankfrank#include "randbuffer" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/randbuffer/driver/0000755000175000017500000000000012222576540015521 5ustar frankfrankbobcat-3.19.01/randbuffer/driver/build0000755000175000017500000000015612222576540016550 0ustar frankfrank#!/bin/sh g++ --std=c++0x -o driver driver.cc -lbobcat # g++ --std=c++0x -o driver driver.cc ../*.o -lbobcat bobcat-3.19.01/randbuffer/driver/driver.h0000644000175000017500000000077412222576540017175 0ustar frankfrank// driver.h #ifndefH_driver_ #defineH_driver_ /* $Id$ $Log$ Revision 1.1 2005/11/11 14:22:42 frank Added local* classes, randstream randbuffer and mailheaders Revision 1.1.1.1 2003/05/31 13:17:04 frank Initial import of Randbuffer Revision 1.1.1.1 2003/05/31 12:41:09 frank Initial import of Randbuffer */ //#include //#include //#include //#include //#include //using namespace std; #endif bobcat-3.19.01/randbuffer/driver/driver.cc0000644000175000017500000000146312222576540017327 0ustar frankfrank#include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { if (argc == 1) { cout << "expect: nruns min max seed\n"; return 1; } Randbuffer rb(A2x(argv[2]), A2x(argv[3]), A2x(argv[4]).to()); istream istr(&rb); for (int idx = A2x(argv[1]); idx--; ) { int c; if (!(istr >> c)) { cout << "extraction failed\n"; break; } cout << "next: " << c << endl; } int count = 0; while (istr.unget()) count++; cout << "number of successful unget()-calls: " << count << endl; istr.clear(); istr >> count; cout << "and read: " << count << endl; return 0; } bobcat-3.19.01/randbuffer/randbuffer0000644000175000017500000000055612226265236016276 0ustar frankfrank#ifndef INCLUDED_BOBCAT_RANDBUFFER_ #define INCLUDED_BOBCAT_RANDBUFFER_ #include #include namespace FBB { class Randbuffer: public std::streambuf { int d_min; double d_max; std::unique_ptr d_buffer; public: Randbuffer(int min, int max, size_t seed); private: virtual int underflow(); }; } #endif bobcat-3.19.01/ranger/0000755000175000017500000000000012223023055013353 5ustar frankfrankbobcat-3.19.01/ranger/ranger4.f0000644000175000017500000000017712223023055015071 0ustar frankfranktemplate Ranger ranger(Data *begin, size_t count) { return Ranger(begin, begin + count); } bobcat-3.19.01/ranger/ranger2.f0000644000175000017500000000016212223023055015061 0ustar frankfranktemplate Ranger ranger(Data *begin, Data *end) { return Ranger(begin, end); } bobcat-3.19.01/ranger/begin.f0000644000175000017500000000013512223023055014605 0ustar frankfrank template Iter const &Ranger::begin() const { return d_begin; } bobcat-3.19.01/ranger/driver/0000755000175000017500000000000012222576537014667 5ustar frankfrankbobcat-3.19.01/ranger/driver/driver.cc0000644000175000017500000000274212222576537016476 0ustar frankfrank#include #include #include using namespace std; using namespace FBB; int main() { vector iv {1, 2, 3, 4, 5}; // display and modify a subrange for(auto &el: ranger(iv.rbegin() + 1, iv.rend() - 1)) cout << el++ << ' '; cout << '\n'; // display a reversed range for(auto &el: ranger(iv.rbegin() + 1, iv.rend() - 1)) cout << el << ' '; cout << '\n'; // same: display using a count for(auto &el: ranger(iv.rbegin() + 1, 3)) cout << el << ' '; cout << '\n'; int intArray[] = {1, 2, 3, 4, 5}; // display and modify elements // in a pointer-based range for(auto &el: ranger(intArray + 1, intArray + 3)) cout << el++ << ' '; cout << '\n'; // data now modified for(auto &el: ranger(intArray + 1, intArray + 3)) cout << el << ' '; cout << '\n'; // using a count rather than an // end-pointer for(auto &el: ranger(intArray + 1, 3)) cout << el << ' '; cout << '\n'; int const constInts[] = {1, 2, 3, 4, 5}; // data can't be modified for(auto &el: ranger(constInts + 1, constInts + 3)) cout << el << ' '; cout << '\n'; } bobcat-3.19.01/ranger/ranger1.f0000644000175000017500000000016012223023055015056 0ustar frankfranktemplate Ranger ranger(Iter &&begin, Iter &&end) { return Ranger(begin, end); } bobcat-3.19.01/ranger/ranger3.f0000644000175000017500000000017412223023055015065 0ustar frankfranktemplate Ranger ranger(Iter &&begin, size_t count) { return Ranger(begin, begin + count); } bobcat-3.19.01/ranger/end.f0000644000175000017500000000012512223023055014266 0ustar frankfranktemplate Iter const &Ranger::end() const { return d_end; } bobcat-3.19.01/ranger/ranger.f0000644000175000017500000000017212223023055015000 0ustar frankfranktemplate Ranger::Ranger(Iter const &begin, Iter const &end) : d_begin(begin), d_end(end) {} bobcat-3.19.01/ranger/ranger0000644000175000017500000000131712223023055014556 0ustar frankfrank#ifndef INCLUDED_BOBCAT_RANGER_ #define INCLUDED_BOBCAT_RANGER_ namespace FBB { template class Ranger { Iter d_begin; Iter d_end; public: Ranger(Iter const &begin, Iter const &end); // .f Iter const &begin() const; // .f Iter const &end() const; // .f }; #include "ranger.f" #include "begin.f" #include "end.f" // Free functions #include "ranger1.f" // ranger(Iter &&begin, Iter &&end) #include "ranger2.f" // ranger(Data *begin, Data *end) #include "ranger3.f" // ranger(Iter &&begin, size_t count) #include "ranger4.f" // ranger(Data *begin, size_t count) } // FBB #endif bobcat-3.19.01/readlinebuf/0000755000175000017500000000000012257325714014373 5ustar frankfrankbobcat-3.19.01/readlinebuf/expansion.f0000644000175000017500000000013112223555745016543 0ustar frankfrankinline ReadLineBuf::Expansion ReadLineBuf::expansion() const { return d_expansion; } bobcat-3.19.01/readlinebuf/readlinebuf0000644000175000017500000000424312223556026016574 0ustar frankfrank#ifndef INCLUDED_BOBCAT_READLINEBUF_ #define INCLUDED_BOBCAT_READLINEBUF_ #include #include #include namespace FBB { struct HistoryExpansion { enum Type { DONT_EXPAND_HISTORY, EXPAND_HISTORY }; enum Expansion { ERROR, NO_EXPANSION, EXPANDED, DONT_EXEC, }; }; class ReadLineBuf: public HistoryExpansion, public std::streambuf { bool d_history; std::string d_prompt; char *d_buffer; char *(ReadLineBuf::*d_readline)(); // calls readLine() or expandLine() std::string (*d_timestamp)(); // return a timestamp Expansion d_expansion; std::string d_expansionError; static std::unique_ptr s_readLineBuf; public: static ReadLineBuf &initialize(std::string const &prompt, Type type = DONT_EXPAND_HISTORY); static ReadLineBuf &initialize(std::string const &prompt, size_t historySize, Type type = DONT_EXPAND_HISTORY); static ReadLineBuf &instance(); virtual ~ReadLineBuf(); void setPrompt(std::string const &prompt = ""); // .f bool setExpansion(Type type); Expansion expansion() const; // .f std::string const &expansionError() const; // .f bool useTimestamps(std::string (*timestamp)() = 0); private: explicit ReadLineBuf(std::string const &prompt, Type type = DONT_EXPAND_HISTORY); explicit ReadLineBuf(std::string const &prompt, size_t historySize, Type type = DONT_EXPAND_HISTORY); virtual int underflow(); char *readLine(); // reads a line, adds it to the history char *expandLine(); // reads a line, expands it if necessary, // then adds it to the history char *nextLine(char *buf); }; #include "setprompt.f" #include "expansion.f" #include "expansionerror.f" } // FBB #endif bobcat-3.19.01/readlinebuf/destructor.cc0000644000175000017500000000017612222576524017103 0ustar frankfrank#include "readlinebuf.ih" ReadLineBuf::~ReadLineBuf() { delete[] d_buffer; if (d_history) clear_history(); } bobcat-3.19.01/readlinebuf/instance.cc0000644000175000017500000000030012222576524016476 0ustar frankfrank#include "readlinebuf.ih" ReadLineBuf &ReadLineBuf::instance() { if (s_readLineBuf.get() == 0) throw logic_error("ReadLineBuf not yet initialized"); return *s_readLineBuf; } bobcat-3.19.01/readlinebuf/underflow.cc0000644000175000017500000000063712222576524016714 0ustar frankfrank#include "readlinebuf.ih" int ReadLineBuf::underflow() { delete[] d_buffer; d_buffer = 0; char *beyond = (this->*d_readline)(); if (beyond == 0) return EOF; setg(d_buffer, d_buffer, beyond); // the static_cast is required to prevent // promotions of 0xff characters to -1, thus returning EOF... return static_cast(*gptr()); } bobcat-3.19.01/readlinebuf/expansionerror.f0000644000175000017500000000013712223556013017610 0ustar frankfrankinline std::string const &ReadLineBuf::expansionError() const { return d_expansionError; } bobcat-3.19.01/readlinebuf/expandline.cc0000644000175000017500000000107012222576524017026 0ustar frankfrank#include "readlinebuf.ih" char *ReadLineBuf::expandLine() { d_expansionError.clear(); char *buf = readline(d_prompt.c_str()); if (buf == 0) return 0; char *expanded; switch (d_expansion = static_cast(1 + history_expand(buf, &expanded))) { case ERROR: d_expansionError = expanded; break; case NO_EXPANSION: break; default: swap(expanded, buf); break; } free(expanded); return nextLine(buf); } bobcat-3.19.01/readlinebuf/readlinebuf2.cc0000644000175000017500000000132512222576524017244 0ustar frankfrank#include "readlinebuf.ih" ReadLineBuf::ReadLineBuf(string const &prompt, size_t historySize, Type type) : d_history(historySize > 0), d_prompt(prompt), d_buffer(0), d_readline(&ReadLineBuf::readLine), d_timestamp(0) { if (!d_history) { if (type == EXPAND_HISTORY) throw std::logic_error("Can't EXPAND_HISTORY without history"); } else { if (type == EXPAND_HISTORY) d_readline = &ReadLineBuf::expandLine; using_history(); stifle_history( historySize > static_cast(numeric_limits::max()) ? numeric_limits::max() : historySize ); } } bobcat-3.19.01/readlinebuf/initialize2.cc0000644000175000017500000000054612222576524017131 0ustar frankfrank#include "readlinebuf.ih" ReadLineBuf &ReadLineBuf::initialize(std::string const &prompt, size_t historySize, Type type) { if (s_readLineBuf.get() != 0) throw logic_error("ReadLineBuf already initialized"); s_readLineBuf.reset(new ReadLineBuf(prompt, historySize, type)); return *s_readLineBuf; } bobcat-3.19.01/readlinebuf/initialize1.cc0000644000175000017500000000043712222576524017127 0ustar frankfrank#include "readlinebuf.ih" ReadLineBuf &ReadLineBuf::initialize(std::string const &prompt, Type type) { if (s_readLineBuf.get() != 0) throw logic_error("ReadLineBuf already initialized"); s_readLineBuf.reset(new ReadLineBuf(prompt, type)); return *s_readLineBuf; } bobcat-3.19.01/readlinebuf/readlinebuf1.cc0000644000175000017500000000052212222576524017241 0ustar frankfrank#include "readlinebuf.ih" ReadLineBuf::ReadLineBuf(string const &prompt, Type type) : d_history(true), d_prompt(prompt), d_buffer(0), d_readline(type == DONT_EXPAND_HISTORY ? &ReadLineBuf::readLine : &ReadLineBuf::expandLine), d_timestamp(0), d_expansion(ERROR) { using_history(); } bobcat-3.19.01/readlinebuf/driver/0000755000175000017500000000000012222576524015665 5ustar frankfrankbobcat-3.19.01/readlinebuf/driver/build0000755000175000017500000000026512222576524016715 0ustar frankfrank#!/bin/bash CMD="g++ --std=c++0x -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib \ -lreadline -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/readlinebuf/driver/driver.cc0000644000175000017500000000232712222576524017473 0ustar frankfrank#include #include #include #include #include #include using namespace std; using namespace FBB; int main() { ReadLineBuf &readlineBuf = ReadLineBuf::initialize("", 10, ReadLineBuf::EXPAND_HISTORY); istream in(&readlineBuf); size_t count = 0; string line; while (true) { ostringstream prompt; prompt << setw(2) << ++count << ": "; readlineBuf.setPrompt(prompt.str()); if (!getline(in, line)) // uses the last-set prompt break; cout << "Retrieved: " << line << "\n" "Expansion status: "; switch (readlineBuf.expansion()) { case ReadLineBuf::ERROR: cout << "ERROR: " << readlineBuf.expansionError() << '\n'; break; case ReadLineBuf::NO_EXPANSION: cout << "no expansion performed\n"; break; case ReadLineBuf::DONT_EXEC: cout << "don't execute the expanded line\n"; break; case ReadLineBuf::EXPANDED: cout << "expansion successfully performed\n"; break; } } } bobcat-3.19.01/readlinebuf/data.cc0000644000175000017500000000012512222576524015610 0ustar frankfrank#include "readlinebuf.ih" std::unique_ptr ReadLineBuf::s_readLineBuf; bobcat-3.19.01/readlinebuf/readline.cc0000644000175000017500000000025112222576524016462 0ustar frankfrank#include "readlinebuf.ih" char *ReadLineBuf::readLine() { char *buf = readline(d_prompt.c_str()); if (buf == 0) return 0; return nextLine(buf); } bobcat-3.19.01/readlinebuf/readlinebuf.ih0000644000175000017500000000027612222576524017201 0ustar frankfrank#include "readlinebuf" #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/readlinebuf/setexpansion.cc0000644000175000017500000000044012222576524017417 0ustar frankfrank#include "readlinebuf.ih" bool ReadLineBuf::setExpansion(Type type) { if (!d_history) return false; d_expansion = ERROR; d_readline = type == DONT_EXPAND_HISTORY ? &ReadLineBuf::readLine : &ReadLineBuf::expandLine; return true; } bobcat-3.19.01/readlinebuf/setprompt.f0000644000175000017500000000013112223555720016565 0ustar frankfrankinline void ReadLineBuf::setPrompt(std::string const &prompt) { d_prompt = prompt; } bobcat-3.19.01/readlinebuf/usetimestamps.cc0000644000175000017500000000025712222576524017610 0ustar frankfrank#include "readlinebuf.ih" bool ReadLineBuf::useTimestamps(string (*timestamp)()) { if (!d_history) return false; d_timestamp = timestamp; return true; } bobcat-3.19.01/readlinebuf/nextline.cc0000644000175000017500000000134412222576524016531 0ustar frankfrank#include "readlinebuf.ih" char *ReadLineBuf::nextLine(char *buf) // malloc allocated buf { string line(buf); if (d_history && not line.empty()) // add line (+ maybe a timestamp) { // to the history add_history(buf); if (d_timestamp) add_history_time((*d_timestamp)().c_str()); } free(buf); // done with the malloc-ed buf. d_buffer = new char[line.length() + 1]; // room for the next line + '\n' // copy buf (+ '\n') to d_buffer d_buffer[line.copy(d_buffer, string::npos)] = '\n'; return d_buffer + line.length() + 1; // returns 'd_buffer.end()' } bobcat-3.19.01/readlinehistory/0000755000175000017500000000000012257325714015320 5ustar frankfrankbobcat-3.19.01/readlinehistory/extracttimestamps.cc0000644000175000017500000000044712222576536021417 0ustar frankfrank#include "readlinehistory.ih" istream &ReadLineHistory::extractTimestamps(istream &in) { string line; string timestamp; while (getline(in, line) && getline(in, timestamp)) { add_history(line.c_str()); add_history_time(timestamp.c_str()); } return in; } bobcat-3.19.01/readlinehistory/oparrow.f0000644000175000017500000000020412223607603017145 0ustar frankfrankinline ReadLineHistory::HistoryElement const *ReadLineHistory::const_iterator::operator->() const { return &operator*(); } bobcat-3.19.01/readlinehistory/extractlines.cc0000644000175000017500000000027112222576536020336 0ustar frankfrank#include "readlinehistory.ih" istream &ReadLineHistory::extractLines(istream &in) { string line; while (getline(in, line)) add_history(line.c_str()); return in; } bobcat-3.19.01/readlinehistory/line.f0000644000175000017500000000013012223606644016405 0ustar frankfrankinline char const *ReadLineHistory::HistoryElement::line() const { return d_line; } bobcat-3.19.01/readlinehistory/instance1.f0000644000175000017500000000012612223606314017342 0ustar frankfrankinline ReadLineHistory &ReadLineHistory::instance() { return s_readLineHistory; } bobcat-3.19.01/readlinehistory/operatorinsert.cc0000644000175000017500000000051512222576536020712 0ustar frankfrank#include "readlinehistory.ih" ostream &FBB::operator<<(ostream &out, ReadLineHistory const &history) { for (auto &he: history) ( history.d_timestamps ? ReadLineHistory::insertHistoryElement : ReadLineHistory::insertLine )(he, out); return out; } bobcat-3.19.01/readlinehistory/timestamps.f0000644000175000017500000000011512223606423017642 0ustar frankfrankinline bool ReadLineHistory::timestamps() const { return d_timestamps; } bobcat-3.19.01/readlinehistory/size.f0000644000175000017500000000011312223606400016417 0ustar frankfrankinline size_t ReadLineHistory::size() const { return history_length; } bobcat-3.19.01/readlinehistory/rbegin.f0000644000175000017500000000017512223606207016730 0ustar frankfrankinline ReadLineHistory::const_reverse_iterator ReadLineHistory::rbegin() const { return const_reverse_iterator(end()); } bobcat-3.19.01/readlinehistory/operatorderef.cc0000644000175000017500000000026312222576536020473 0ustar frankfrank#include "readlinehistory.ih" ReadLineHistory::HistoryElement const &ReadLineHistory::const_iterator::operator*() const { return d_element.set(history_list()[d_idx]); } bobcat-3.19.01/readlinehistory/readlinehistory.ih0000644000175000017500000000023312223607323021035 0ustar frankfrank#include "readlinehistory" #include #include using namespace std; using namespace FBB; #include "opdec.f" #include "opdecpost.f" bobcat-3.19.01/readlinehistory/timestamp.f0000644000175000017500000000014212223606724017463 0ustar frankfrankinline char const *ReadLineHistory::HistoryElement::timestamp() const { return d_timestamp; } bobcat-3.19.01/readlinehistory/opincpost.f0000644000175000017500000000020512223607226017474 0ustar frankfrankinline ReadLineHistory::const_iterator ReadLineHistory::const_iterator::operator++(int) { return const_iterator(d_idx++); } bobcat-3.19.01/readlinehistory/rend.f0000644000175000017500000000017512223606224016411 0ustar frankfrankinline ReadLineHistory::const_reverse_iterator ReadLineHistory::rend() const { return const_reverse_iterator(begin()); } bobcat-3.19.01/readlinehistory/instance2.f0000644000175000017500000000020712223606327017347 0ustar frankfrankinline ReadLineHistory &ReadLineHistory::instance(bool useTimestamps) { return s_readLineHistory.setTimestampsIO(useTimestamps); } bobcat-3.19.01/readlinehistory/set.cc0000644000175000017500000000034712222576536016430 0ustar frankfrank#include "readlinehistory.ih" ReadLineHistory::HistoryElement const &ReadLineHistory::HistoryElement::set(HIST_ENTRY const *element) { d_line = element->line; d_timestamp = element->timestamp; return *this; } bobcat-3.19.01/readlinehistory/inserthistoryelement.cc0000644000175000017500000000034712222576536022135 0ustar frankfrank#include "readlinehistory.ih" void ReadLineHistory::insertHistoryElement(HistoryElement const &he, std::ostream &out) { out << he.line() << '\n' << he.timestamp() << '\n'; } bobcat-3.19.01/readlinehistory/settimestampsio.f0000644000175000017500000000020512223606021020700 0ustar frankfrankinline ReadLineHistory &ReadLineHistory::setTimestampsIO(bool useTimestamps) { d_timestamps = useTimestamps; return *this; } bobcat-3.19.01/readlinehistory/maxsize.f0000644000175000017500000000012312223606476017143 0ustar frankfrankinline size_t ReadLineHistory::maxSize() const { return history_max_entries; } bobcat-3.19.01/readlinehistory/operatorextract.cc0000644000175000017500000000041412222576536021056 0ustar frankfrank#include "readlinehistory.ih" istream &FBB::operator>>(istream &in, ReadLineHistory &history) { if (!in) return in; clear_history(); if (history.d_timestamps) return history.extractTimestamps(in); return history.extractLines(in); } bobcat-3.19.01/readlinehistory/begin.f0000644000175000017500000000015012223606075016542 0ustar frankfrankinline ReadLineHistory::const_iterator ReadLineHistory::begin() const { return const_iterator(0); } bobcat-3.19.01/readlinehistory/driver/0000755000175000017500000000000012222576536016615 5ustar frankfrankbobcat-3.19.01/readlinehistory/driver/build0000755000175000017500000000040412222576536017640 0ustar frankfrank#!/bin/bash LIBS="-lreadline -lbobcat" #CMD="g++ --std=c++0x -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib \ # ${LIBS} -s" CMD="g++ --std=c++0x -o driver -Wall driver.cc ${LIBS} -s" echo $CMD $CMD bobcat-3.19.01/readlinehistory/driver/driver.cc0000644000175000017500000000261412222576536020422 0ustar frankfrank#include #include #include #include #include #include using namespace std; using namespace FBB; void showHis(ReadLineHistory::HistoryElement const &element) { cout << element.timestamp() << ": " << element.line() << '\n'; } string timestamp() { return DateTime().rfc2822(); }; int main(int argc, char **argv) { ReadLineStream in("? ", ReadLineBuf::EXPAND_HISTORY); in.useTimestamps(×tamp); cout << "Enter some lines, end the input using ctrl-d\n"; string line; while (getline(in, line)) ; // argument means: write/read // history timestamps ReadLineHistory &history = ReadLineHistory::instance(argc > 1); cout << "All lines, from the first to the last:\n"; for_each(history.begin(), history.end(), showHis); cout << "\n" "All lines, from the last to the first:\n"; for_each(history.rbegin(), history.rend(), showHis); cout << "\n" "History out and in:\n" "\n"; ofstream hisout("history.out"); hisout << history; hisout.close(); ifstream hisin("history.out"); hisin >> history; cout << "All lines, from the first to the last:\n"; for_each(history.begin(), history.end(), showHis); } bobcat-3.19.01/readlinehistory/data.cc0000644000175000017500000000012312222576536016536 0ustar frankfrank#include "readlinehistory.ih" ReadLineHistory ReadLineHistory::s_readLineHistory; bobcat-3.19.01/readlinehistory/constiterator2.f0000644000175000017500000000012712223607076020446 0ustar frankfrankinline ReadLineHistory::const_iterator::const_iterator(size_t idx) : d_idx(idx) {} bobcat-3.19.01/readlinehistory/historyelement1.f0000644000175000017500000000014012223606550020607 0ustar frankfrankinline ReadLineHistory::HistoryElement::HistoryElement() : d_line(0), d_timestamp(0) {} bobcat-3.19.01/readlinehistory/opeq.f0000644000175000017500000000025112223607510016417 0ustar frankfrankinline bool ReadLineHistory::const_iterator::operator==( const_iterator const &rhs) const { return d_idx == rhs.d_idx; } bobcat-3.19.01/readlinehistory/opneq.f0000644000175000017500000000025112223607557016610 0ustar frankfrankinline bool ReadLineHistory::const_iterator::operator!=( const_iterator const &rhs) const { return not (*this == rhs); } bobcat-3.19.01/readlinehistory/end.f0000644000175000017500000000014512223606113016221 0ustar frankfrankinline ReadLineHistory::const_iterator ReadLineHistory::end() const { return const_iterator(); } bobcat-3.19.01/readlinehistory/constiterator1.f0000644000175000017500000000013012223607056020435 0ustar frankfrankinline ReadLineHistory::const_iterator::const_iterator() : d_idx(history_length) {} bobcat-3.19.01/readlinehistory/opdec.f0000644000175000017500000000017612223607341016555 0ustar frankfrankinline ReadLineHistory::const_iterator &ReadLineHistory::const_iterator::operator--() { --d_idx; return *this; } bobcat-3.19.01/readlinehistory/insertline.cc0000644000175000017500000000021712222576536020005 0ustar frankfrank#include "readlinehistory.ih" void ReadLineHistory::insertLine(HistoryElement const &he, std::ostream &out) { out << he.line() << '\n'; } bobcat-3.19.01/readlinehistory/readlinehistory0000644000175000017500000001063312223607634020450 0ustar frankfrank#ifndef INCLUDED_BOBCAT_READLINEHISTORY_ #define INCLUDED_BOBCAT_READLINEHISTORY_ #include #include #include namespace FBB { class ReadLineHistory; std::ostream &operator<<(std::ostream &out, ReadLineHistory const &history); std::istream &operator>>(std::istream &out, ReadLineHistory &history); class ReadLineHistory { friend std::ostream &operator<<(std::ostream &out, ReadLineHistory const &history); friend std::istream &operator>>(std::istream &out, ReadLineHistory &history); static ReadLineHistory s_readLineHistory; bool d_timestamps; public: class HistoryElement { friend class ReadLineHistory; char const *d_line; char const *d_timestamp; public: char const *line() const; // .f char const *timestamp() const; // .f private: HistoryElement(); // 1.f HistoryElement const &set(HIST_ENTRY const *element); }; class const_iterator: public std::iterator { friend class ReadLineHistory; friend class std::reverse_iterator; size_t d_idx; mutable HistoryElement d_element; public: const_iterator &operator++(); // opinc.f const_iterator operator++(int); // opincpost.f bool operator==(const_iterator const &rhs) const; // opeq.f bool operator!=(const_iterator const &rhs) const; // opneq.f HistoryElement const &operator*() const; HistoryElement const *operator->() const; // oparrow.f private: const_iterator(); // last element 1.f const_iterator(size_t idx); // 2.f // for the reverse iter. const_iterator &operator--(); // opdec.f const_iterator operator--(int); // opdecpost.f }; typedef std::reverse_iterator const_reverse_iterator; ReadLineHistory(ReadLineHistory const &other) = delete; ReadLineHistory &operator=(ReadLineHistory const &rhs) = delete; const_iterator begin() const; // begin of the history .f const_iterator end() const; // end of the history .f const_reverse_iterator rbegin() const; // .f const_reverse_iterator rend() const; // .f ReadLineHistory &setTimestampsIO(bool useTimestamps); // .f size_t size() const; // .f size_t maxSize() const; // .f bool timestamps() const; // .f static ReadLineHistory &instance(); // 1.f static ReadLineHistory &instance(bool useTimestamps); // 2.f private: ReadLineHistory(); // .f static void insertHistoryElement(HistoryElement const &he, std::ostream &out); static void insertLine(HistoryElement const &he, std::ostream &out); static std::istream &extractTimestamps(std::istream &in); static std::istream &extractLines(std::istream &in); }; #include "readlinehistory1.f" #include "begin.f" #include "end.f" #include "instance1.f" #include "instance2.f" #include "maxsize.f" #include "rbegin.f" #include "rend.f" #include "settimestampsio.f" #include "size.f" #include "timestamps.f" // ======= HistoryElement members ============ #include "historyelement1.f" #include "line.f" #include "timestamp.f" // ======== const_iterator members #include "constiterator1.f" #include "constiterator2.f" #include "oparrow.f" #include "opeq.f" #include "opinc.f" #include "opincpost.f" #include "opneq.f" } // FBB #endif bobcat-3.19.01/readlinehistory/readlinehistory1.f0000644000175000017500000000005512223610547020747 0ustar frankfrankinline ReadLineHistory::ReadLineHistory() {} bobcat-3.19.01/readlinehistory/opdecpost.f0000644000175000017500000000020512223607354017460 0ustar frankfrankinline ReadLineHistory::const_iterator ReadLineHistory::const_iterator::operator--(int) { return const_iterator(d_idx--); } bobcat-3.19.01/readlinehistory/opinc.f0000644000175000017500000000017612223607132016571 0ustar frankfrankinline ReadLineHistory::const_iterator &ReadLineHistory::const_iterator::operator++() { ++d_idx; return *this; } bobcat-3.19.01/readlinestream/0000755000175000017500000000000012223611107015075 5ustar frankfrankbobcat-3.19.01/readlinestream/setexpansion.f0000644000175000017500000000014512223610216017764 0ustar frankfrankinline bool ReadLineStream::setExpansion(Type type) { return d_readLineBuf.setExpansion(type); } bobcat-3.19.01/readlinestream/expansion.f0000644000175000017500000000015512223610243017251 0ustar frankfrankinline ReadLineStream::Expansion ReadLineStream::expansion() const { return d_readLineBuf.expansion(); } bobcat-3.19.01/readlinestream/expansionerror.f0000644000175000017500000000016012223610304020315 0ustar frankfrankinline std::string const &ReadLineStream::expansionError() const { return d_readLineBuf.expansionError(); } bobcat-3.19.01/readlinestream/driver/0000755000175000017500000000000012222576536016407 5ustar frankfrankbobcat-3.19.01/readlinestream/driver/build0000755000175000017500000000036212222576536017435 0ustar frankfrank#!/bin/bash CMD="g++ --std=c++0x -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib \ -lreadline -lbobcat -s" CMD="g++ --std=c++0x -o driver -Wall driver.cc -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/readlinestream/driver/driver.cc0000644000175000017500000000216212222576536020212 0ustar frankfrank#include #include #include #include #include #include using namespace std; using namespace FBB; int main() { ReadLineStream in("", 10, ReadLineBuf::EXPAND_HISTORY); size_t count = 0; string line; while (true) { ostringstream prompt; prompt << setw(2) << ++count << ": "; in.setPrompt(prompt.str()); if (!getline(in, line)) // uses the last-set prompt break; cout << "Retrieved: " << line << "\n" "Expansion status: "; switch (in.expansion()) { case ReadLineBuf::ERROR: cout << "ERROR: " << in.expansionError() << '\n'; break; case ReadLineBuf::NO_EXPANSION: cout << "no expansion performed\n"; break; case ReadLineBuf::DONT_EXEC: cout << "don't execute the expanded line\n"; break; case ReadLineBuf::EXPANDED: cout << "expansion successfully performed\n"; break; } } } bobcat-3.19.01/readlinestream/readlinestream2.f0000644000175000017500000000037612223610125020332 0ustar frankfrankinline ReadLineStream::ReadLineStream(std::string const &prompt, size_t historySize, Type type) : std::istream(&ReadLineBuf::initialize(prompt, historySize, type)), d_readLineBuf(ReadLineBuf::instance()) {} bobcat-3.19.01/readlinestream/readlinestream1.f0000644000175000017500000000026612223610541020331 0ustar frankfrankinline ReadLineStream::ReadLineStream(std::string const &prompt, Type type) : std::istream(&ReadLineBuf::initialize(prompt, type)), d_readLineBuf(ReadLineBuf::instance()) {} bobcat-3.19.01/readlinestream/readlinestream0000644000175000017500000000227612223610402020023 0ustar frankfrank#ifndef INCLUDED_BOBCAT_READLINESTREAM_ #define INCLUDED_BOBCAT_READLINESTREAM_ #include #include namespace FBB { class ReadLineStream: public HistoryExpansion, public std::istream { ReadLineBuf &d_readLineBuf; public: explicit ReadLineStream(std::string const &prompt, // 1.f Type type = DONT_EXPAND_HISTORY); explicit ReadLineStream(std::string const &prompt, // 2.f size_t historySize, Type type = DONT_EXPAND_HISTORY); void setPrompt(std::string const &prompt = ""); // .f bool setExpansion(Type type); // .f Expansion expansion() const; // .f std::string const &expansionError() const; // .f bool useTimestamps(std::string (*timestamp)()); }; #include "readlinestream1.f" #include "readlinestream2.f" #include "setprompt.f" #include "setexpansion.f" #include "expansion.f" #include "expansionerror.f" #include "usetimestamps.f" } // FBB #endif bobcat-3.19.01/readlinestream/readlinestream.ih0000644000175000017500000000010512222576536020431 0ustar frankfrank#include "readlinestream" using namespace std; using namespace FBB; bobcat-3.19.01/readlinestream/setprompt.f0000644000175000017500000000015212223610150017274 0ustar frankfrankinline void ReadLineStream::setPrompt(std::string const &prompt) { d_readLineBuf.setPrompt(prompt); } bobcat-3.19.01/readlinestream/usetimestamps.f0000644000175000017500000000017512223610333020152 0ustar frankfrankinline bool ReadLineStream::useTimestamps(std::string (*timestamp)()) { return d_readLineBuf.useTimestamps(timestamp); } bobcat-3.19.01/redirector/0000755000175000017500000000000012257325714014255 5ustar frankfrankbobcat-3.19.01/redirector/swallow.cc0000644000175000017500000000027112222576534016254 0ustar frankfrank#include "redirector.ih" void Redirector::swallow(int alternateFd) const { if (dup2(d_fd, alternateFd) < 0) throw Exception() << "Redirector::swallow(): " << errnodescr; } bobcat-3.19.01/redirector/redirector1.f0000644000175000017500000000007012223611273016633 0ustar frankfrankinline Redirector::Redirector(int fd) : d_fd(fd) {} bobcat-3.19.01/redirector/accessvia.f0000644000175000017500000000012712223611314016350 0ustar frankfrankinline void Redirector::accessVia(int alternateFd) const { swallow(alternateFd); } bobcat-3.19.01/redirector/redirector0000644000175000017500000000106312223611327016331 0ustar frankfrank#ifndef INCLUDED_BOBCAT_REDIRECTOR_ #define INCLUDED_BOBCAT_REDIRECTOR_ namespace FBB { class Redirector { int d_fd; public: enum StandardFilenos { STDIN = 0, STDOUT, STDERR }; explicit Redirector(int fd); // 1.f void accessVia(int alternateFd) const; // .f void swallow(int alternateFd) const; void through(int alternateFd) const; }; #include "redirector1.f" #include "accessvia.f" } // FBB #endif bobcat-3.19.01/redirector/driver/0000755000175000017500000000000012222576534015550 5ustar frankfrankbobcat-3.19.01/redirector/driver/build0000755000175000017500000002670712222576534016611 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/driver string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } //#define BUILD_LIBRARY #define BUILD_PROGRAM "driver" #define COMPILER "g++" #define COPT "-Wall -I../../inc" #define LOPT "" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "../../lib" // local namespace is: FBB // using-declarations generated for: std:FBB // qt-mt can be used to select the threaded QT library //#define QT "qt" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current, // contains name of current dir. programname; // the name of the program to create int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); #ifdef GRAMMAR_LINES system("./grambuild lines"); #else system("./grambuild"); #endif chdir(".."); if ( exists("grammar") && "grammar" younger "parse.cc" ) // new parser needed #ifdef BISON_FLAGS exec("bisonc++", BISON_FLAGS, "grammar"); #else exec("bisonc++", "grammar"); #endif chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || ( exists("../parser/parser.h") && "../parser/parser.h" younger "yylex.cc" ) ) ) exec("flex", interactive, "lexer"); chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; programname = BUILD_PROGRAM; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD if (exists("parser")) // subdir parser exists { CLASSES += "parser "; parser(); } if (exists("scanner")) // subdir scanner exists { CLASSES += "scanner "; scanner(); } #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library) { printf("\n"); system("mv ../../lib/libbobcat.so ../../lib/libbobcat.OFF"); exec(COMPILER, "-o", programname, ofiles, libs, "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); system("mv ../../lib/libbobcat.OFF ../../lib/libbobcat.so"); printf("ok: ", programname, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "driver.cc", // program source "driver" // static program library ); #else cpp_make ( "", "driver" // static- or so-library ); #endif } bobcat-3.19.01/redirector/driver/driver.cc0000644000175000017500000000065412222576534017357 0ustar frankfrank/* driver.cc */ #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { Redirector redirector(Redirector::STDOUT); redirector.swallow(Redirector::STDERR); cerr << "This appears at the standard output stream\n" "use `a.out > /dev/null' to suppress this message" << endl; return 0; } bobcat-3.19.01/redirector/through.cc0000644000175000017500000000031512222576534016243 0ustar frankfrank#include "redirector.ih" void Redirector::through(int alternateFd) const { if (dup2(d_fd, alternateFd) < 0) throw Exception() << "Redirector::through(): " << errnodescr; ::close(d_fd); } bobcat-3.19.01/redirector/redirector.ih0000644000175000017500000000014012222576534016734 0ustar frankfrank#include "redirector" #include #include using namespace FBB; bobcat-3.19.01/refcount/0000755000175000017500000000000012257325714013740 5ustar frankfrankbobcat-3.19.01/refcount/destructor.cc0000644000175000017500000000006112222576534016442 0ustar frankfrank#include "refcount.ih" RefCount::~RefCount() {} bobcat-3.19.01/refcount/refcount.ih0000644000175000017500000000010012222576534016076 0ustar frankfrank#include "refcount" using namespace std; using namespace FBB; bobcat-3.19.01/refcount/release.cc0000644000175000017500000000014512222576534015667 0ustar frankfrank#include "refcount.ih" void RefCount::release() { if (--d_refcount == 0) delete this; } bobcat-3.19.01/refcount/refcount0000644000175000017500000000234712222576534015516 0ustar frankfrank#ifndef INCLUDED_BOBCAT_REFCOUNT_ #define INCLUDED_BOBCAT_REFCOUNT_ #include #include namespace FBB { class RefCount { mutable size_t d_refcount; protected: RefCount(); RefCount(RefCount const &other); // used by clone() virtual ~RefCount(); public: size_t refcount() const; void release(); template static X *share(X const *x); template static X &modifying(X **x); private: virtual RefCount *clone() const = 0; }; inline RefCount::RefCount() : d_refcount(1) {} inline RefCount::RefCount(RefCount const &other) // used by clone() : d_refcount(1) {} inline size_t RefCount::refcount() const { return d_refcount; } template X *RefCount::share(X const *x) { x->d_refcount++; return const_cast(x); } template X &RefCount::modifying(X **x) { if ((*x)->d_refcount != 1) { (*x)->d_refcount--; *x = dynamic_cast ( reinterpret_cast(*x)->clone() ); if (!*x) throw std::bad_cast(); } return **x; } } // FBB #endif bobcat-3.19.01/refcount/driver/0000755000175000017500000000000012222576534015233 5ustar frankfrankbobcat-3.19.01/refcount/driver/build0000755000175000017500000000004312222576534016255 0ustar frankfrank#!/bin/bash g++ driver.cc ../*.cc bobcat-3.19.01/refcount/driver/driver.cc0000644000175000017500000001342412222576534017041 0ustar frankfrank/* driver.cc */ #include #include #include #include "../refcount" using namespace std; using namespace FBB; // The class Data uses reference counting. Data are shared until they are // modified. class Data: public RefCount { static size_t s_n; // count the number of objects in use public: Data() // all other constructors are built like this: { // using RefCount's default constructor. s_n++; cout << "Data(), " << s_n << " Data objects created\n"; } virtual ~Data() { s_n--; cout << "~Data(), " << s_n << " Data objects left\n"; } string accessor() const { ostringstream ostr; ostr << "calling Data::accessor(). Data at " << this; return ostr.str(); } void modifier() // a plain modifier { cout << "calling Data::modifier(). Data at " << this << endl; } // support function for operator>>() istream &extract(istream &istr) { cout << "extraction from istream. " << "Enter a non-empty line of text" << endl; string s; getline(istr, s); cout << "Read: " << s << endl; return istr; } // another modifier: operator+=() Data &operator+=(Data const &rvalue) { cout << "calling Data::operator+=(): @`" << this << "' += @`" << &rvalue << "'\n"; return *this; } private: Data &operator=(Data const &other); // NI Data(Data const &other) // The copy constructor MUST call RefCount's : // CC. Data(Data) is a convenience function // for clone() and should not be available to RefCount(other) // clients, thus enforcing the use of { // clone() / share() / release() s_n++; cout << "Data(Data const &), " << s_n << " Data objects created\n"; } virtual RefCount *clone() const { cout << "Data::clone()\n"; return new Data(*this); } }; // Client: uses a pointer to a Data object. It is implemented in an // almost standard way. Deviations are: // *. Copy(): should call share() rather than new Data(*d_dataPtr) // *. Destroy(): should call release() rather than delete d_dataPtr; // *. non-const members modifying d_dataPtr's data" // should call Data:modifying() first. class Client { // modifying friend // see below at modifier() friend istream &operator>>(istream &istr, Client &c) { return Data::modifying(&c.d_dataPtr).extract(istr); } Data *d_dataPtr; public: // Constructors, destructor, overloaded assignment operator: all // follow my standard copy() / destroy() approach. Client() // new object, creates its own data : // use new Data(...) to initialize. d_dataPtr(new Data()) {} ~Client() { destroy(); } Client(Client const &other) { copy(other); } Client &operator=(Client const &other) { if (this != &other) { destroy(); copy(other); } return *this; } string accessor() const // accessors shadow Data's members { return d_dataPtr->accessor(); } // modifiers call modifying first void modifier() // simple modifier { Data::modifying(&d_dataPtr).modifier(); } // arithmetic assignment modifier Client &operator+=(Client const &other) { Data::modifying(&d_dataPtr).operator+=(*other.d_dataPtr); return *this; } private: void copy(Client const &other) // copying is sharing: call share() { d_dataPtr = Data::share(other.d_dataPtr); } void destroy() // destroying is disassociation: call { // release d_dataPtr->release(); } }; size_t Data::s_n = 0; Client const operator+(Client const &lvalue, Client const &rvalue) { return Client(lvalue) += rvalue; } int main() { cout << "Construction:\n"; Client c; cout << "Extraction c from cin:\n"; cin >> c; cout << "c's Modifier called:\n"; c.modifier(); cout << "operator += :\n"; c += c; cout << "operator + :\n"; c + c; cout << "Copy construction:\n"; Client c2(c); cout << "Assignment:\n"; c = c2; cout << "Accessors:\n"; cout << "access c: " << c.accessor() << endl; cout << "access c2: " << c2.accessor() << endl; cout << "operator += :\n"; c += c; cout << "c's Modifier called:\n"; c.modifier(); cout << "Accessors:\n"; cout << "access c: " << c.accessor() << endl; cout << "access c2: " << c2.accessor() << endl; cout << "c2's Modifier called:\n"; c2.modifier(); cout << "resetting refcount to 2:\n"; c = c2; cout << "Extraction c from cin:\n"; cin >> c; cout << "End of program:\n"; } bobcat-3.19.01/repeat/0000755000175000017500000000000012223613065013363 5ustar frankfrankbobcat-3.19.01/repeat/repeat0000644000175000017500000000172212223612717014573 0ustar frankfrank#ifndef INCLUDED_BOBCAT_REPEAT_ #define INCLUDED_BOBCAT_REPEAT_ #include #include namespace FBB { template struct Repeat__; template <> struct Repeat__ { template static void call(Fun fun, Params &&...params); // 1.f }; template <> struct Repeat__ { template static void call(Class &obj, Member member, Params &&...params); // 2.f template static void call(Class const &obj, Member member, // 3.f Params &&...params); }; template inline void repeat(Counter counter, First &&first, Params &&...params); // .f #include "call1.f" #include "call2.f" #include "call3.f" #include "repeat.f" } // FBB #endif bobcat-3.19.01/repeat/call2.f0000644000175000017500000000037412223613053014530 0ustar frankfranktemplate inline void Repeat__::call(Class &obj, Member member, Params &&...params) { (obj.*member)(std::forward(params)...); } bobcat-3.19.01/repeat/repeat.f0000644000175000017500000000053112223612762015014 0ustar frankfranktemplate void repeat(Counter counter, First &&first, Params &&...params) { for (; counter; --counter) Repeat__::isClass>::call( std::forward(first), std::forward(params)...); } bobcat-3.19.01/repeat/call3.f0000644000175000017500000000040612223613017014525 0ustar frankfranktemplate inline void Repeat__::call(Class const &obj, Member member, Params &&...params) { (obj.*member)(std::forward(params)...); } bobcat-3.19.01/repeat/call1.f0000644000175000017500000000023112223613032014514 0ustar frankfranktemplate inline void Repeat__::call(Fun fun, Params &&...params) { fun(std::forward(params)...); } bobcat-3.19.01/repeat/driver/0000755000175000017500000000000012222576524014665 5ustar frankfrankbobcat-3.19.01/repeat/driver/build0000755000175000017500000000006112222576524015707 0ustar frankfrank#!/bin/bash g++ --std=c++0x -o driver driver.cc bobcat-3.19.01/repeat/driver/driver.cc0000644000175000017500000000240412222576524016467 0ustar frankfrank#include #include #include #include "../repeat" using namespace std; using namespace FBB; class Object { public: void member(int argc, char **argv) const; void member2(size_t &rept, int argc, char **argv); }; void Object::member(int argc, char **argv) const { cout << "member called\n"; copy(argv, argv + argc, ostream_iterator(cout, "\n")); } void Object::member2(size_t &rept, int argc, char **argv) { cout << "member2 called, iteration " << rept++ << "\n"; copy(argv, argv + argc, ostream_iterator(cout, "\n")); } void fun() { cout << "Fun called\n"; } int main(int argc, char **argv) { Object object; cout << "\n" "*** The number of arguments determines the repeat-count ***\n\n"; cout << "Fun without arguments:\n"; repeat(argc, fun); cout << "Object receiving argc and argv:\n"; repeat(argc, object, &Object::member, argc, argv); cout << "Object receiving argc and argv, showing the iteration count:\n"; size_t count = 0; repeat(argc, object, &Object::member2, count, argc, argv); Object const obj; cout << "Const Object receiving argc and argv:\n"; repeat(argc, obj, &Object::member, argc, argv); } bobcat-3.19.01/scripts/0000755000175000017500000000000012222576534013602 5ustar frankfrankbobcat-3.19.01/scripts/check1.20.00000755000175000017500000000103612222576534015244 0ustar frankfrank#!/bin/bash if [ $# -eq 0 ] then echo " Find from the current working directory all files containing the classes Arg Glob OneKey Pipe ServerSocket SocketBase User or Xpointer Run this script with any argument to obtain a list of filenames only. Press Enter to continue and search for files or ^C to abort" read else OPT=-l fi /bin/grep -E $OPT \ '\b(Arg|Glob|OneKey|Pipe|ServerSocket|SocketBase|User|Xpointer)\b'\ `/usr/bin/find . -type f \ -exec /usr/bin/perl -e 'print "{}\n" if -T "{}";' \;` bobcat-3.19.01/selector/0000755000175000017500000000000012257325714013733 5ustar frankfrankbobcat-3.19.01/selector/addfd.cc0000644000175000017500000000021112222576534015276 0ustar frankfrank#include "selector.ih" void Selector::addFd(fd_set *set, int fd) { FD_SET(fd, set); if (fd >= d_max) d_max = fd + 1; } bobcat-3.19.01/selector/checkset.cc0000644000175000017500000000031312222576534016030 0ustar frankfrank#include "selector.ih" int Selector::checkSet(int *index, fd_set &set) { int &idx = *index; while (idx < d_max && !FD_ISSET(idx, &set)) ++idx; return idx == d_max ? -1 : idx++; } bobcat-3.19.01/selector/addreadfd.f0000644000175000017500000000010412223756237015774 0ustar frankfrankinline void Selector::addReadFd(int fd) { addFd(&d_read, fd); } bobcat-3.19.01/selector/nready.f0000644000175000017500000000006412223755751015365 0ustar frankfrankinline int Selector::nReady() { return d_ret; } bobcat-3.19.01/selector/setalarm.cc0000644000175000017500000000046112222576534016053 0ustar frankfrank#include "selector.ih" void Selector::setAlarm(int sec, int usec) { d_alarm.tv_sec = sec; d_alarm.tv_usec = usec; long long testTime = usec + 1000000LL * sec; if (testTime < 0 || testTime > numeric_limits::max() * 1000000LL) throw Exception(1) << "Selector::setAlarm()"; } bobcat-3.19.01/selector/selector.cc0000644000175000017500000000031012222576534016054 0ustar frankfrank/* selector.cc */ #include "selector.ih" Selector::Selector() { FD_ZERO(&d_read); FD_ZERO(&d_write); FD_ZERO(&d_except); noAlarm(); d_max = 0; } bobcat-3.19.01/selector/selector0000644000175000017500000000423212223757460015477 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SELECTOR_ #define INCLUDED_BOBCAT_SELECTOR_ #include namespace FBB { class Selector { fd_set d_read; fd_set d_write; fd_set d_except; fd_set d_ret_read; fd_set d_ret_write; fd_set d_ret_except; timeval d_alarm; int d_max; int d_ret; int d_readidx; int d_writeidx; int d_exceptidx; public: Selector(); int wait(); // nReady() and the get...() members // perform defined behavior only after // wait() returns. int nReady(); // number of available fd's. 0: timeout .f // occurred, -1: select() failed. int exceptFd(); // .f int readFd(); // -1 if no more available .f // descriptors otherwise the next // available fd in each category int writeFd(); // .f void setAlarm(int sec, int usec = 0); void noAlarm(); // .f void addReadFd(int fd); // .f void addWriteFd(int fd); // .f void addExceptFd(int fd); // .f void rmReadFd(int fd); // .f void rmWriteFd(int fd); // .f void rmExceptFd(int fd); // .f private: int checkSet(int *index, fd_set &set); void addFd(fd_set *set, int fd); }; #include "addexceptfd.f" #include "addreadfd.f" #include "addwritefd.f" #include "exceptfd.f" #include "noalarm.f" #include "nready.f" #include "readfd.f" #include "rmexceptfd.f" #include "rmreadfd.f" #include "rmwritefd.f" #include "writefd.f" } // FBB #endif bobcat-3.19.01/selector/driver/0000755000175000017500000000000012222576534015226 5ustar frankfrankbobcat-3.19.01/selector/driver/build0000755000175000017500000004300412222576534016254 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/driver // script generated by the C++ icmake script version 2.02 /* Configurable defines for the build script: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. When defined as an EMPTY STRING, the static library libXXX.a is created: all programs linked to this library will themselves contain the code of the required object modules. This will result in code duplication over different programs linked to this library. When defined as a VERSION STRING, e.g., 1.0.4, a shared library libXXX.so.VERSION is constructed, as well as the links libXXX.so.MAINVERSION and libXXX.so (e.g. 1.0.0 creates libXXX.so.1.0.0, libXXX.so.1 and libXXX.so). Note that with a shared library, the library is always constructed fresh from the compiled object files. But programs linked to this library will SHARE the code stored in the shared library. These programs will therefore tend to be relatively small. Also note that `ldconfig -v' might be required after installing a shared library (libXXX.so) for the first time, so that the linker knows of its existence (in ld.so.cache) BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (default: defined). COMPILER: The compiler to use. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking LOCAL_NAMESPACE:The namespace that you, the programmer, use yourself. USING: List of :-separated namespaces to be used in sources and .ih files, appearing in `using' directives. USING does NOT automatically include LOCAL_NAMESPACE: add your LOCAL_NAMESPACE name to this list if want a `using' directive for your own namespace as well. Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY "" #define BUILD_PROGRAM #define COMPILER "g++" #define COPT "-Wall" #define ECHO_REQUEST 1 //#define GDB "-g" #define ICMAKE "/usr/bin/icmake" #define LIBS "bobcat" #define LIBPATH "../.." // local namespace is: FBB // using-declarations generated for: std:FBB // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path libso, // symbolic link to so.major library path libsomajor, // lib.so.major path ofiles, // wildcards for o-files sources, // sources to be used current; // contains name of current dir. int nClasses, // number of classes/subdirectories program, // 1: program is built so_lib; // 1: so_lib is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", interactive, "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; so_lib = 0; #else program = 0; #endif; #ifdef BUILD_LIBRARY if (strlen(BUILD_LIBRARY)) so_lib = !program; else so_lib = 0; #else if (!program) { printf("no program, no library ?\n"); exit(1); } #endif if (so_lib) copt += " -fPIC"; cwd = chdir("."); #ifdef GRAMBUILD CLASSES = "parser scanner "; if (exists("parser")) // subdir parser exists parser(); if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY if (!so_lib) // keep all files with so libs files = altered(files, library);// keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { printf("\n"); exec(COMPILER, "-o", exe, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef GRAMBUILD "-lfl", #endif "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* L I N K S O . I M */ void link_solib(string library) { string gdb; #ifdef GDB gdb = GDB; #endif #ifdef BUILD_LIBRARY int index; list sofiles, version; version = strtok(BUILD_LIBRARY, "."); libso = "lib" + library + ".so"; libxxx = libso + "."; libsomajor = libxxx + element(0, version); libxxx += BUILD_LIBRARY; for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir(current); // chdir to a class directory. prefix_class((string)index); chdir(cwd); // go back to parent dir } if (!makelist("o/*.o")) ofiles = "*/o/*.o"; printf("\n"); exec(COMPILER, gdb, "-shared", "-Wl,-soname," + libsomajor, "-o", libxxx, ofiles, libs, "-L.", libpath, lopt ); printf("ok: ", libxxx, "\n"); for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir(current); // chdir to a class directory. rm_class_prefix((string)index); chdir(cwd); // go back to parent dir } exec("ln", "-sf", libxxx, libsomajor); printf("ok: ", libsomajor, "\n"); exec("ln", "-sf", libsomajor, libso); printf("ok: ", libso, "\n"); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int index; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY if (!so_lib) libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { current = element(index, classes); // next class to process chdir(current); // change to directory current = "subdir " + current; std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY if (!so_lib) { // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir } else { link_solib(library); // separate processing for so-lib return; } #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); #ifdef GRAMBUILD libs += " -lfl"; #endif cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "driver.cc", // program source "driver", // static program library "driver" // binary program ); #else cpp_make ( "", "driver", // static- or so-library "" ); #endif } bobcat-3.19.01/selector/driver/driver.cc0000644000175000017500000000145712222576534017037 0ustar frankfrank#include "../selector" #include "../../errno/errno" #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { Selector selector; selector.setAlarm(5); // every 5 secs: alarm fires selector.addReadFd(STDIN_FILENO); // look also at cin try { while (true) { if (!selector.wait()) // 0: alarm fires cout << "Are you still there?" << endl; else { string s; if (!getline(cin, s) || !s.length()) return 0; cout << "Thank you for: " << s << endl; } } } catch (Errno const &e) { cout << e.why() << endl; } } bobcat-3.19.01/selector/readfd.f0000644000175000017500000000011712223756035015323 0ustar frankfrankinline int Selector::readFd() { return checkSet(&d_readidx, d_ret_read); } bobcat-3.19.01/selector/writefd.f0000644000175000017500000000014112223756106015536 0ustar frankfrankinline int Selector::writeFd() { return checkSet(&d_writeidx, d_ret_write); } bobcat-3.19.01/selector/rmreadfd.f0000644000175000017500000000010412223756364015663 0ustar frankfrankinline void Selector::rmReadFd(int fd) { FD_CLR(fd, &d_read); } bobcat-3.19.01/selector/noalarm.f0000644000175000017500000000011712223756152015527 0ustar frankfrankinline void Selector::noAlarm() { d_alarm.tv_sec = d_alarm.tv_usec = -1; } bobcat-3.19.01/selector/rmexceptfd.f0000644000175000017500000000011012223756420016226 0ustar frankfrankinline void Selector::rmExceptFd(int fd) { FD_CLR(fd, &d_except); } bobcat-3.19.01/selector/selector.ih0000644000175000017500000000015712222576534016100 0ustar frankfrank#include "selector" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/selector/rmwritefd.f0000644000175000017500000000010612223756401016074 0ustar frankfrankinline void Selector::rmWriteFd(int fd) { FD_CLR(fd, &d_write); } bobcat-3.19.01/selector/addexceptfd.f0000644000175000017500000000011012223756274016347 0ustar frankfrankinline void Selector::addExceptFd(int fd) { addFd(&d_except, fd); } bobcat-3.19.01/selector/wait.cc0000644000175000017500000000067612222576534015217 0ustar frankfrank#include "selector.ih" int Selector::wait() { timeval t = d_alarm; d_ret_read = d_read; d_ret_write = d_write; d_ret_except = d_except; d_readidx = 0; d_writeidx = 0; d_exceptidx = 0; d_ret = select(d_max, &d_ret_read, &d_ret_write, &d_ret_except, t.tv_sec == -1 && t.tv_usec == -1 ? 0 : &t); if (d_ret < 0) throw Exception() << "Selector::wait()"; return d_ret; } bobcat-3.19.01/selector/exceptfd.f0000644000175000017500000000014512223756002015673 0ustar frankfrankinline int Selector::exceptFd() { return checkSet(&d_exceptidx, d_ret_except); } bobcat-3.19.01/selector/addwritefd.f0000644000175000017500000000010612223756255016215 0ustar frankfrankinline void Selector::addWriteFd(int fd) { addFd(&d_write, fd); } bobcat-3.19.01/serversocket/0000755000175000017500000000000012257325714014632 5ustar frankfrankbobcat-3.19.01/serversocket/serversocket1.cc0000644000175000017500000000102112222576534017733 0ustar frankfrank#include "serversocket.ih" ServerSocket::ServerSocket(size_t port) : SocketBase(port), // uses INADDR_ANY -> current host. d_msg(0) { int val = 1; // Make sure the socket is reusable upon restarts if (setsockopt(socket(), SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int))) { d_msg = "ServerSocket::ServerSocket(port) setsockopt() failed"; return; } if (bind(socket(), sockaddrPtr(), size()) < 0) d_msg = "ServerSocket::ServerSocket(port)"; } bobcat-3.19.01/serversocket/accept.cc0000644000175000017500000000121712222576534016401 0ustar frankfrank#include "serversocket.ih" SocketBase ServerSocket::accept() { sockaddr_in address; socklen_t size = sizeof(address); int sock = ::accept ( socket(), reinterpret_cast(&address), &size ); if (sock < 0) throw Exception() << "ServerSocket::accept(): " << errnodescr; class MakeSocketBase: public SocketBase { public: MakeSocketBase(int socket, sockaddr_in const &addr) : SocketBase(socket, addr) {} }; return MakeSocketBase(sock, address); } bobcat-3.19.01/serversocket/serversocket0000644000175000017500000000060612222576534017276 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SERVERSOCKET_ #define INCLUDED_BOBCAT_SERVERSOCKET_ #include #include namespace FBB { class ServerSocket: public SocketBase { int d_err; char const *d_msg; public: explicit ServerSocket(size_t port); void listen(size_t backlog = 5, bool blocking = true); SocketBase accept(); }; } // FBB #endif bobcat-3.19.01/serversocket/driver/0000755000175000017500000000000012222576534016125 5ustar frankfrankbobcat-3.19.01/serversocket/driver/build0000755000175000017500000003101712222576534017154 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/server // script generated by the C++ icmake script version 1.61 /* Configurable defines for the build script: BISON++: only to be defined if bison++ is to be used in the subdirectory 'parser' on the file 'grammar', generating 'parser.cc' and 'parser.h' in that directory. FLEX++: only to be defined if flex++ is to be used in the subdirectory 'scanner' on the file 'yylex', generating 'yylex.cc' CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ //#define BISON++ //#define FLEX++ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* COMPILER: "g++" for C++ sources. Do not change this, unless you're sure you want something else. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking USE_LIBRARY: define this if you want a library for the object modules. Undefined by default: so NO LIBRARY IS USED. PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed. (default: defined) RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //Do not change the next define unless you know what you're doing: #define COMPILER "g++" // COPT: the set of C-options #define COPT "-Wall" #define ECHO_REQUEST ON // #define GDB // Extra libraries required. Remove lib and .a from the library names. // E.g., #define LIBS "m Xt" to link libm.a and libXt.a explicitly // Specify libs from the most specific to the most general one. #define LIBS "bobcat" // Extra library-paths required. // E.g., #define LIBPATH "/some/path /some/other/path" to search these paths // apart from the default paths #define LIBPATH "" // uncomment if you WANT to use a library // #define USE_LIBRARY #define PROGRAM #define RELINK // DO NOT ALTER THINGS BELOW THIS LINE string // contain options for libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, lopt, libxxxa; // expanded lib-name int relink; // internally used: != 0 to relink string ofiles, // wildcards for o-files sources, // sources to be used wild, // wildcard of extension current; // contains name of current dir. /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list #ifdef USE_LIBRARY objfile = change_ext(file, "o"); // make obj-filename #else objfile = "./o/" + change_ext(file, "o"); // make obj-filename #endif if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* parser.im */ void parser() { chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); } /* scanner.im */ void scanner() { chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", #ifdef INTERACTIVE "-I", #endif "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef USE_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { #ifndef RELINK if ( relink // new library, new main.obj || !exists(exe) // final program doesn't exist ) #endif { printf("\n"); exec(COMPILER, "-o", exe, #ifdef USE_LIBRARY "-l" + library, #else ofiles, #endif libs, "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; #ifndef USE_LIBRARY if (!exists("o")) system("mkdir o"); #endif if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) { #ifdef USE_LIBRARY exec(COMPILER, "-c " COPT + " " + copt + " " + nextfile); #else exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o") + " " COPT + " " + copt + " " + nextfile); #endif } relink = 1; printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { list arlist, objlist; string to, from; objlist = makelist("*.o"); if (!sizeof(objlist)) return; printf("\n"); relink = 1; exec("ar", "rvs", library, "*.o"); exec("rm", "*.o"); printf("\n"); } void prefix_class(string class_id) { list o_files; string o_file; int i; o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(wild, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix, .a suffix if main is given here, libmain.a is created) string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int n, index; list classes; string cwd; #ifdef BISON++ CLASSES += "parser "; if (exists("parser")) // subdir parser exists parser(); #endif #ifdef FLEX++ CLASSES += "scanner "; if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes cwd = chdir("."); ofiles = "o/*.o"; // std set of o-files classes = strtok(CLASSES, " "); // list of classes if (n = sizeof(classes)) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use wild = sources; // make library name libxxxa = chdir(".") + "lib" + library + ".a"; // first process all classes for (index = 0; index < n; index++) { current = element(index, classes); // next class to process chdir(current); // change to directory current = "subdir " + current; std_cpp (libxxxa); // compile all files chdir( cwd); // go back to parent dir } current = "auxiliary " + wild + " files"; std_cpp (libxxxa); // compile all files in current dir for (index = 0; index < n; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. #ifdef USE_LIBRARY prefix_class((string)index); // prefix class-number for .o files updatelib(libxxxa); #endif chdir(cwd); // go back to parent dir } current = ""; // no class anymore #ifdef USE_LIBRARY updatelib(libxxxa); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); #ifdef FLEX++ libs += " -lfl"; #endif cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); } void main() { echo(ECHO_REQUEST); sources = "*.cc"; setlibs(); #ifdef GDB copt = "-g"; #endif #ifdef PROGRAM cpp_make ( "server.cc", // program source "server", // program library "server" // binary program ); #else cpp_make ( "", "server", // program library "" ); #endif } bobcat-3.19.01/serversocket/driver/server.cc0000644000175000017500000000357212222576534017751 0ustar frankfrank#include #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc == 1) { cerr << "Provide server port number\n"; return 1; } size_t portnr = A2x(argv[1]); ServerSocket server(portnr); cerr << "server listens on port " << argv[1] << endl; cerr << "serversocket returns:\n" << "address = " << server.dottedDecimalAddress() << endl << "port = " << server.port() << endl; int fd = server.socket(); // open the socket's descriptor cout << "File descriptor of the socket is " << fd << endl << "The server terminates when it receives a single `q' on a line\n" "A connection is terminated when no input is received anymore.\n" "Then another connection is possible" << endl; server.listen(); // listen in blocking mode while (true) { SocketBase fdb = server.accept(); int fd = fdb.socket(); cerr << "Client FD = " << fd << ", " << endl << "address = " << fdb.dottedDecimalAddress() << ", " << endl << "communication through port " << fdb.port() << endl; IFdStream in(fd); // stream to read from client OFdStream out(fd); // stream to write to client string cmd; while (getline(in, cmd)) { cout << "Got: " << cmd << endl; out << "Got: " << cmd << "\r" << endl; if (cmd[0] == 'q') return 0; } cout << "Ready for another connection\n"; } } catch (Errno const &err) { cerr << err.why() << endl << "Server socket on port " << argv[1] << " can't be opened" << endl; return -1; } bobcat-3.19.01/serversocket/serversocket.ih0000644000175000017500000000026712222576534017700 0ustar frankfrank#include "serversocket" #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/serversocket/listen.cc0000644000175000017500000000120212222576534016432 0ustar frankfrank#include "serversocket.ih" void ServerSocket::listen(size_t backlog, bool blocking) { static char name[] = "ServerSocket::listen()"; verify(); // verify the SocketBase construction if (d_msg) throw Exception(1) << d_msg; int sock = socket(); if (::listen(sock, backlog) < 0) throw Exception() << name << ": " << errnodescr; if (blocking) return; if ( fcntl ( sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK ) == -1 ) throw Exception() << name << ": " << errnodescr; } bobcat-3.19.01/sharedblock/0000755000175000017500000000000012244427062014367 5ustar frankfrankbobcat-3.19.01/sharedblock/sharedblock0000644000175000017500000000062712244427062016600 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SHAREDBLOCK_ #define INCLUDED_BOBCAT_SHAREDBLOCK_ #include namespace FBB { class SharedBlock { SharedMutex d_mutex; int d_id = -1; public: void lock(); void unlock(); int id() const; void setID(int id); }; #include "id.f" #include "setid.f" #include "lock.f" #include "unlock.f" } // FBB #endif bobcat-3.19.01/sharedblock/sharedblock.ih0000644000175000017500000000010212241123502017150 0ustar frankfrank#include "sharedblock" using namespace std; using namespace FBB; bobcat-3.19.01/sharedblock/id.f0000644000175000017500000000007012242144057015125 0ustar frankfrankinline int SharedBlock::id() const { return d_id; } bobcat-3.19.01/sharedblock/lock.f0000644000175000017500000000007012242144110015447 0ustar frankfrankinline void SharedBlock::lock() { d_mutex.lock(); } bobcat-3.19.01/sharedblock/setid.f0000644000175000017500000000007212242144034015636 0ustar frankfrankinline void SharedBlock::setID(int id) { d_id = id; } bobcat-3.19.01/sharedblock/unlock.f0000644000175000017500000000007412242144140016021 0ustar frankfrankinline void SharedBlock::unlock() { d_mutex.unlock(); } bobcat-3.19.01/sharedmemory/0000755000175000017500000000000012257325714014612 5ustar frankfrankbobcat-3.19.01/sharedmemory/remove1.cc0000644000175000017500000000012712241414101016455 0ustar frankfrank#include "sharedmemory.ih" void SharedMemory::remove() { lockAll(); kill(); } bobcat-3.19.01/sharedmemory/offset.f0000644000175000017500000000012312242372575016244 0ustar frankfrankinline std::streamsize SharedMemory::offset() const { return d_pos.offset(); } bobcat-3.19.01/sharedmemory/sharedmemory3.cc0000644000175000017500000000030212241370123017661 0ustar frankfrank#include "sharedmemory.ih" SharedMemory::SharedMemory(int id) : d_id(id), d_sharedSegment(static_cast(SharedSegment::attach(id))) { d_pos.reset(d_sharedSegment); } bobcat-3.19.01/sharedmemory/clear.cc0000644000175000017500000000015312241356435016203 0ustar frankfrank#include "sharedmemory.ih" void SharedMemory::clear() { lockAll(); clearAll(); unlockAll(); } bobcat-3.19.01/sharedmemory/blockavailable.cc0000644000175000017500000000063712241452706020055 0ustar frankfrank#include "sharedmemory.ih" bool SharedMemory::blockAvailable(size_t idx) { if (d_data == 0) // no data available return false; if (d_pos.blockIdx() == idx) // already loaded: done return true; d_sharedSegment->unlock(d_pos.blockIdx()); // clear an existing lock d_lockCount = 0; d_data = SharedSegment::detach(d_data); return false; } bobcat-3.19.01/sharedmemory/destructor.cc0000644000175000017500000000023312241370216017303 0ustar frankfrank#include "sharedmemory.ih" SharedMemory::~SharedMemory() { SharedSegment::detach(d_data, false); SharedSegment::detach(d_sharedSegment, false); } bobcat-3.19.01/sharedmemory/operatorassign.f0000644000175000017500000000014612242372714020016 0ustar frankfrankinline SharedMemory &SharedMemory::operator=(SharedMemory &&tmp) { swap(tmp); return *this; } bobcat-3.19.01/sharedmemory/insert.cc0000644000175000017500000000105712241452552016422 0ustar frankfrank#include "sharedmemory.ih" ostream &SharedMemory::insert(ostream &out) const { if (d_sharedSegment == 0) return out << "No shared data avaiable"; out << "ID of shared memory segment: " << d_id << '\n'; if (d_data == 0) out << "No shared memory data block attached\n"; else out << "Shared memory block attached at address " << static_cast(d_data) << ", block index = " << d_pos.blockIdx() << '\n'; return out << *d_sharedSegment << '\n' << d_pos; } bobcat-3.19.01/sharedmemory/id.f0000644000175000017500000000007112242372635015351 0ustar frankfrankinline int SharedMemory::id() const { return d_id; } bobcat-3.19.01/sharedmemory/sharedmemory2.cc0000644000175000017500000000052312241427352017674 0ustar frankfrank#include "sharedmemory.ih" SharedMemory::SharedMemory(size_t maxSize, SizeUnit sizeUnit, size_t access) { size_t nBlocks; size_t segmentSize = computeSegmentSize(&nBlocks, maxSize, sizeUnit); d_sharedSegment = SharedSegment::create(&d_id, nBlocks, segmentSize, access); d_pos.reset(d_sharedSegment); } bobcat-3.19.01/sharedmemory/get.cc0000644000175000017500000000042512241452606015673 0ustar frankfrank#include "sharedmemory.ih" int SharedMemory::get() { int ret; map(); if (d_pos.eof()) ret = EOF; else { lock(d_pos.blockIdx()); ret = *ptr(); ++d_pos; unlock(d_pos.blockIdx()); } return ret; } bobcat-3.19.01/sharedmemory/unlock.cc0000644000175000017500000000032712241664771016420 0ustar frankfrank#include "sharedmemory.ih" void SharedMemory::unlock(size_t idx) { //cerr << "UNlocking " << idx << ": " << d_lockCount << '\n'; if (d_lockCount && --d_lockCount == 0) d_sharedSegment->unlock(idx); } bobcat-3.19.01/sharedmemory/computesegmentsize.cc0000644000175000017500000000303212241361706021043 0ustar frankfrank#include "sharedmemory.ih" // Memory computation // P: standard page size // x: required multiplication for P to compute the blockSize // b: sizeof(Block): blockEntry // h: size of the header: sizeof(SharedSegment) - b // M: max available memory // Each entry of SharedSegment::block points to xP bytes // If there are n entries in block, then n*xP == M // // The block array in the SharedSegment segment itself consists of xP - h bytes, // holding (xP - h) / e entries. // // Therefore, (xP - h) / b * xP == M. // // -> sqr(P) / b * sqr(x) - h P / b * x - M = 0 // --- a --- --- b --- - c - // // The quadratic equation is solved for x, which is rounded upward to compute // the real maximum memory size. size_t SharedMemory::computeSegmentSize( size_t *nBlocks, long long maxMemory, SizeUnit sizeUnit) { typedef SharedBlock Entry; maxMemory <<= sizeUnit; double a = static_cast(PAGESIZE) * PAGESIZE / sizeof(Entry); double b = -static_cast(sizeof(SharedSegment) - sizeof(Entry)) * PAGESIZE / sizeof(Entry); double c = -maxMemory; size_t factor = static_cast( // size of allocated blocks ceil((-b + sqrt(b * b - 4 * a * c)) / (2 * a)) ); size_t segmentSize = factor * PAGESIZE; *nBlocks = (segmentSize - (sizeof(SharedSegment) - sizeof(Entry))) / sizeof(Entry); return segmentSize; } bobcat-3.19.01/sharedmemory/unlockall.cc0000644000175000017500000000050312241760214017072 0ustar frankfrank#include "sharedmemory.ih" void SharedMemory::unlockAll() { for ( size_t idx = 0, end = d_sharedSegment->nBlocks(); idx != end; ++idx ) unlock(idx); //cerr << "UNlocking shared segment\n"; d_sharedSegment->nReadableUnlock(); //cerr << "UNlockAll done\n"; } bobcat-3.19.01/sharedmemory/clearall.cc0000644000175000017500000000024112241452631016665 0ustar frankfrank#include "sharedmemory.ih" void SharedMemory::clearAll() { d_pos.reset(d_sharedSegment); d_lockCount = 0; d_data = SharedSegment::detach(d_data); } bobcat-3.19.01/sharedmemory/write.cc0000644000175000017500000000143612242375466016262 0ustar frankfrank#include "sharedmemory.ih" int SharedMemory::write(char const *data, streamsize len) { if (d_pos.atMaxOffset()) return -1; streamsize begin = d_pos.offset(); //cerr << "write at " << begin << ", len = " << len << '\n'; while (len != 0) { int nChars = writeBlock(data, len); // locks, updates d_offset //cerr << "wrote " << nChars << '\n'; if (nChars == -1) // hit maxOffset() break; len -= nChars; data += nChars; d_pos += nChars; d_sharedSegment->updateNreadable(d_pos.offset()); //cerr << "Next offset: " << d_pos.offset() << ", len = " << len << '\n'; } //cerr << ".write wrote " << (d_pos.offset() - begin) << " chars\n"; return d_pos.offset() - begin; } bobcat-3.19.01/sharedmemory/swap.f0000644000175000017500000000012612242372660015726 0ustar frankfrankinline void SharedMemory::swap(SharedMemory &other) { FBB::fswap(*this, other); } bobcat-3.19.01/sharedmemory/map1.cc0000644000175000017500000000033712241664356015763 0ustar frankfrank#include "sharedmemory.ih" void SharedMemory::map() { size_t idx = d_pos.blockIdx(); // block idx to use //cerr << "map: using block " << idx << '\n'; if (not blockAvailable(idx)) map(idx); } bobcat-3.19.01/sharedmemory/lock.cc0000644000175000017500000000032412241664400016037 0ustar frankfrank#include "sharedmemory.ih" void SharedMemory::lock(size_t idx) { //cerr << "locking " << idx << ": " << d_lockCount << '\n'; if (d_lockCount == 0) d_sharedSegment->lock(idx); ++d_lockCount; } bobcat-3.19.01/sharedmemory/map2.cc0000644000175000017500000000072612241425770015761 0ustar frankfrank#include "sharedmemory.ih" // private, only called by load. void SharedMemory::map(size_t idx) { int id = (*d_sharedSegment)[idx].id(); bool newData = id == -1; if (newData) { d_sharedSegment->lock(idx); id = d_sharedSegment->newData(idx); } d_data = static_cast(SharedSegment::attach(id)); if (newData) { memset(d_data, 0, d_sharedSegment->size(id)); d_sharedSegment->unlock(idx); } } bobcat-3.19.01/sharedmemory/ptr.cc0000644000175000017500000000033412241400776015721 0ustar frankfrank#include "sharedmemory.ih" char *SharedMemory::ptr() { if (d_pos.atMaxOffset()) return 0; map(); // map block[d_blockIdx] return d_data + d_pos.blockOffset(); } bobcat-3.19.01/sharedmemory/kill.cc0000644000175000017500000000026212241426153016044 0ustar frankfrank#include "sharedmemory.ih" void SharedMemory::kill() { clearAll(); d_sharedSegment->deleteSegment(d_id); d_sharedSegment = SharedSegment::detach(d_sharedSegment); } bobcat-3.19.01/sharedmemory/readblock.cc0000644000175000017500000000154212241665033017043 0ustar frankfrank#include "sharedmemory.ih" int SharedMemory::readBlock(char *data, size_t len) { if (d_pos.eof()) return -1; streamsize maxReadable = d_sharedSegment->nReadable(); map(); streamsize nReadable = d_pos.eos(); //cerr << "eos: " << nReadable << " maxReadable: " << maxReadable; if (maxReadable < nReadable) nReadable = maxReadable; size_t remaining = nReadable - d_pos.offset(); //cerr << " remaining: " << remaining; if (remaining < len) len = remaining; //cerr << " len = " << len << ", blockIdx = " << d_pos.blockIdx() << //" blockOffset = " << d_pos.blockOffset() << '\n'; lock(d_pos.blockIdx()); memcpy(data, d_data + d_pos.blockOffset(), len); //cerr << "-->"; //cerr.write(d_data + d_pos.blockOffset(), len); //cerr << "<--\n"; unlock(d_pos.blockIdx()); return len; } bobcat-3.19.01/sharedmemory/maxoffset.f0000644000175000017500000000013112242372617016746 0ustar frankfrankinline std::streamsize SharedMemory::maxOffset() const { return d_pos.maxOffset(); } bobcat-3.19.01/sharedmemory/nreadable.f0000644000175000017500000000014412242372550016667 0ustar frankfrankinline std::streamsize SharedMemory::nReadable() const { return d_sharedSegment->nReadable(); } bobcat-3.19.01/sharedmemory/read.cc0000644000175000017500000000112412241664436016032 0ustar frankfrank#include "sharedmemory.ih" int SharedMemory::read(char *data, streamsize len) { if (d_pos.eof()) return -1; streamsize begin = d_pos.offset(); //cerr << "read at " << begin << ", len = " << len << '\n'; while (len != 0) { int nReceived = readBlock(data, len); //cerr << "read " << nReceived << '\n'; if (nReceived == -1) break; len -= nReceived; data += nReceived; d_pos += nReceived; //cerr << "Next offset: " << d_pos.offset() << ", len = " << len << '\n'; } return d_pos.offset() - begin; } bobcat-3.19.01/sharedmemory/seek.cc0000644000175000017500000000021612237401357016043 0ustar frankfrank#include "sharedmemory.ih" ios::pos_type SharedMemory::seek(ios::off_type offset, ios::seekdir way) { return d_pos.seek(offset, way); } bobcat-3.19.01/sharedmemory/lockall.cc0000644000175000017500000000054412241760176016543 0ustar frankfrank#include "sharedmemory.ih" // unchecked: d_lockCount should be 0 void SharedMemory::lockAll() { for ( size_t idx = 0, end = d_sharedSegment->nBlocks(); idx != end; ++idx ) lock(idx); //cerr << "locking shared segment\n"; d_sharedSegment->nReadableLock(); //cerr << "lockAll done\n"; } bobcat-3.19.01/sharedmemory/showmanyc.cc0000644000175000017500000000016612237417734017136 0ustar frankfrank#include "sharedmemory.ih" streamsize SharedMemory::showmanyc() { return d_pos.eof() ? 0 : d_pos.showmanyc(); } bobcat-3.19.01/sharedmemory/writeblock.cc0000644000175000017500000000102412241664472017263 0ustar frankfrank#include "sharedmemory.ih" int SharedMemory::writeBlock(char const *data, size_t len) { if (d_pos.atMaxOffset()) return -1; map(); size_t remaining = d_pos.eos() - d_pos.offset(); //cerr << "eos: " << d_pos.eos() << " remaining: " << remaining; if (remaining < len) len = remaining; //cerr << " len = " << len << ", blockIdx = " << d_pos.blockIdx() << '\n'; lock(d_pos.blockIdx()); memcpy(d_data + d_pos.blockOffset(), data, len); unlock(d_pos.blockIdx()); return len; } bobcat-3.19.01/sharedmemory/put.cc0000644000175000017500000000052112241452346015722 0ustar frankfrank#include "sharedmemory.ih" int SharedMemory::put(int ch) { char *cp = ptr(); // ptr() loads the proper data segment if (cp == 0) return EOF; lock(d_pos.blockIdx()); *cp = ch; ++d_pos; unlock(d_pos.blockIdx()); d_sharedSegment->updateNreadable(d_pos.offset()); return ch; } bobcat-3.19.01/sharedmemory/operatorinsert.f0000644000175000017500000000015412242372746020042 0ustar frankfrankinline std::ostream &operator<<(std::ostream &out, SharedMemory const &mem) { return mem.insert(out); } bobcat-3.19.01/sharedmemory/sharedmemory0000644000175000017500000001064512244427062017235 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SHAREDMEMORY_ #define INCLUDED_BOBCAT_SHAREDMEMORY_ #include #include #include namespace FBB { class SharedSegment; struct SharedEnum__ { enum SizeUnit { kB = 10, MB = 20, GB = 30 }; }; class SharedMemory: public virtual SharedEnum__ { friend std::ostream &operator<<(std::ostream &out, SharedMemory const &mem); enum { PAGESIZE = 1 << 12 }; // updated by the non-default constructors. int d_id = -1; // id of SharedSegment SharedSegment *d_sharedSegment = 0; // points to the attached shared // memory. This is NOT a pointer // to dynamically allocated memory // but a static_cast pointer to // the attached shared data segment SharedPos d_pos; size_t d_lockCount = 0; // # of nested locks char *d_data = 0; // pointer to shared memory data public: SharedMemory() = default; SharedMemory(SharedMemory const &other) = delete; SharedMemory(size_t maxSize, SizeUnit sizeUnit, size_t access = 0600); // 2: creation mode; SharedMemory(int id); // 3 ~SharedMemory(); SharedMemory &operator=(SharedMemory &&tmp); std::streamsize showmanyc(); std::streamsize nReadable() const; // beyond last readable byte std::streamsize offset() const; // read/write offset std::streamsize maxOffset() const; char *ptr(); // 0 if at maxOffset // returns -1 if inaccessible std::ios::pos_type seek(std::ios::off_type offset, std::ios::seekdir way = std::ios::beg); int id() const; // id of the d_sharedSegment segment int put(int ch); // put char at d_offset (locks), // ch == EOF immediately returns EOF // write len bytes at d_offset // locks, returns #written or -1 int write(char const *data, std::streamsize len); int get(); // get char from d_segmentData // locks), or EOF // read len chars, return nRead, locks int read(char *data, std::streamsize len); void clear(); // clear all existing data and reduce // until only the segment at // d_sharedSegment void swap(SharedMemory &other); // after kill/remove: shared segment is unusable void kill(); // delete all shared segments w/o locks void remove(); // delete all shared segments. private: std::ostream &insert(std::ostream &out) const; // lockAll: d_lockCount should be 0. void lockAll(); // lock all block[] mutexes void unlockAll(); // unlock all block[] mutexes void lock(size_t idx); // (recursively) lock block idx void unlock(size_t idx); // unlock block idx void clearAll(); // clear without locking bool blockAvailable(size_t idx); void map(); // 1 maps shared data to d_data void map(size_t idx); // 2 only called by load int writeBlock(char const *data, size_t len); // locks, returns // #written or -1 int readBlock(char *data, size_t len); // same, but now reads // both update offset static size_t computeSegmentSize( size_t *nBlocks, long long maxMemory, SizeUnit sizeUnit); }; #include "id.f" #include "maxoffset.f" #include "nreadable.f" #include "offset.f" #include "operatorassign.f" #include "operatorinsert.f" #include "swap.f" } // FBB #endif bobcat-3.19.01/sharedmemory/sharedmemory.ih0000644000175000017500000000016612242372401017623 0ustar frankfrank#include "sharedmemory" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/sharedmutex/0000755000175000017500000000000012257325714014444 5ustar frankfrankbobcat-3.19.01/sharedmutex/sharedmutex.ih0000644000175000017500000000013712242370676017321 0ustar frankfrank#include "sharedmutex" #include using namespace std; using namespace FBB; bobcat-3.19.01/sharedmutex/destructor.cc0000644000175000017500000000011112241122545017130 0ustar frankfrank#include "sharedmutex.ih" SharedMutex::~SharedMutex() { unlock(); } bobcat-3.19.01/sharedmutex/sharedmutex1.cc0000644000175000017500000000104112240231205017340 0ustar frankfrank#include "sharedmutex.ih" SharedMutex::SharedMutex() { pthread_mutexattr_t mutex_attr; pthread_mutexattr_init(&mutex_attr); // pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&d_mutex, &mutex_attr); // pthread_condattr_t cond_attr; // // pthread_condattr_init(&cond_attr); // pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); // pthread_cond_init(&d_condvar, &cond_attr); } bobcat-3.19.01/sharedmutex/lock.cc0000644000175000017500000000026112241130762015670 0ustar frankfrank#include "sharedmutex.ih" void SharedMutex::lock() { if (pthread_mutex_lock(&d_mutex) != 0) throw Exception() << "SharedMutex::lock: failed to lock the segment"; } bobcat-3.19.01/sharedmutex/sharedmutex0000644000175000017500000000073012242370663016715 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SHAREDMUTEX_ #define INCLUDED_BOBCAT_SHAREDMUTEX_ #include namespace FBB { class SharedMutex { pthread_mutex_t d_mutex; public: SharedMutex(); SharedMutex(SharedMutex const &other) = delete; ~SharedMutex(); // does unlock SharedMutex &operator=(SharedMutex const &rhs) = delete; void lock(); void unlock(); }; #include "unlock.f" } // FBB #endif bobcat-3.19.01/sharedmutex/unlock.f0000644000175000017500000000011212242370653016074 0ustar frankfrankinline void SharedMutex::unlock() { pthread_mutex_unlock(&d_mutex); } bobcat-3.19.01/sharedpos/0000755000175000017500000000000012257325714014103 5ustar frankfrankbobcat-3.19.01/sharedpos/offset.f0000644000175000017500000000011212242373300015516 0ustar frankfrankinline std::streamsize SharedPos::offset() const { return d_offset; } bobcat-3.19.01/sharedpos/insert.cc0000644000175000017500000000046712241453556015724 0ustar frankfrank#include "sharedpos.ih" ostream &SharedPos::insert(ostream &out) const { return out << "Maximum possible offset = " << d_maxOffset << "\n" "Current offset = " << d_offset << ", located in block " << blockIdx(); } bobcat-3.19.01/sharedpos/eos.f0000644000175000017500000000017312242373122015027 0ustar frankfrankinline std::streamsize SharedPos::eos() const { return static_cast(blockIdx() + 1) * segmentSize(); } bobcat-3.19.01/sharedpos/segmentsize.f0000644000175000017500000000013112242373357016602 0ustar frankfrankinline size_t SharedPos::segmentSize() const { return d_sharedData->segmentSize(); } bobcat-3.19.01/sharedpos/sharedpos.ih0000644000175000017500000000013512242373066016411 0ustar frankfrank#include "sharedpos" #include using namespace std; using namespace FBB; bobcat-3.19.01/sharedpos/blockoffset.f0000644000175000017500000000011312242373256016544 0ustar frankfrankinline size_t SharedPos::blockOffset() const { return d_blockOffset; } bobcat-3.19.01/sharedpos/eof.f0000644000175000017500000000013112242373142015006 0ustar frankfrankinline bool SharedPos::eof() const { return d_offset >= d_sharedData->nReadable(); } bobcat-3.19.01/sharedpos/atmaxoffset.f0000644000175000017500000000012312242373210016553 0ustar frankfrankinline bool SharedPos::atMaxOffset() const { return d_offset == d_maxOffset; } bobcat-3.19.01/sharedpos/maxoffset.f0000644000175000017500000000012012242373163016232 0ustar frankfrankinline std::streamsize SharedPos::maxOffset() const { return d_maxOffset; } bobcat-3.19.01/sharedpos/nreadable.f0000644000175000017500000000013612242373336016164 0ustar frankfrankinline std::streamsize SharedPos::nReadable() const { return d_sharedData->nReadable(); } bobcat-3.19.01/sharedpos/seek.cc0000644000175000017500000000056012241456622015336 0ustar frankfrank#include "sharedpos.ih" ios::pos_type SharedPos::seek(ios::off_type offset, ios::seekdir way) { if (way == ios::cur) offset += d_offset; else if (way == ios::end) offset += nReadable(); if (0 <= offset && offset <= d_maxOffset) { d_offset = offset; update(); } else offset = -1; return offset; } bobcat-3.19.01/sharedpos/blockidx.f0000644000175000017500000000010512242373232016035 0ustar frankfrankinline size_t SharedPos::blockIdx() const { return d_blockIdx; } bobcat-3.19.01/sharedpos/reset.cc0000644000175000017500000000041612241453521015524 0ustar frankfrank#include "sharedpos.ih" void SharedPos::reset(SharedSegment *sharedData) { d_sharedData = sharedData; d_offset = 0; d_maxOffset = static_cast(sharedData->nBlocks()) * segmentSize(); } bobcat-3.19.01/sharedpos/operatorplusplus.cc0000644000175000017500000000013512241454750020050 0ustar frankfrank#include "sharedpos.ih" void SharedPos::operator++() { ++d_offset; update(); } bobcat-3.19.01/sharedpos/showmanyc.cc0000644000175000017500000000056212241453503016414 0ustar frankfrank#include "sharedpos.ih" streamsize SharedPos::showmanyc() const { streamsize available = nReadable(); streamsize end = eos(); // offset at end of current segment if (end > available) // end cannot exceed writeoffset end = available; return d_offset >= end ? 0 : end - d_offset; } bobcat-3.19.01/sharedpos/update.cc0000644000175000017500000000073512241454666015703 0ustar frankfrank#include "sharedpos.ih" void SharedPos::update() { bool beyondMax = d_offset > d_maxOffset; streamsize offset; if (beyondMax) { offset = d_offset; d_offset = d_maxOffset; } size_t segSize = segmentSize(); d_blockIdx = d_offset / segSize; d_blockOffset = d_offset % segSize; if (beyondMax) throw Exception() << "Offset (" << offset << ") exceeds maxOffset (" << d_maxOffset << ')'; } bobcat-3.19.01/sharedpos/operatorplusis.cc0000644000175000017500000000014712241454606017503 0ustar frankfrank#include "sharedpos.ih" void SharedPos::operator+=(size_t len) { d_offset += len; update(); } bobcat-3.19.01/sharedpos/operatorinsert.f0000644000175000017500000000016512242373406017327 0ustar frankfrankinline std::ostream &operator<<(std::ostream &out, SharedPos const &sharedPos) { return sharedPos.insert(out); } bobcat-3.19.01/sharedpos/sharedpos0000644000175000017500000000422612244427062016015 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SHAREDPOS_ #define INCLUDED_BOBCAT_SHAREDPOS_ #include #include #include namespace FBB { class SharedPos { friend std::ostream &operator<<(std::ostream &out, SharedPos const &pos); SharedSegment *d_sharedData = 0; // setup must have been called to // initialize data members std::streamsize d_maxOffset = 0; // max. possible offset, given nBlocks std::streamsize d_offset = 0; // next location to write size_t d_blockIdx = 0; size_t d_blockOffset = 0; public: void reset(SharedSegment *sharedData); bool eof() const; // true if no char can be read // because offset >= writeoffset bool atMaxOffset() const; std::streamsize showmanyc() const; std::streamsize maxOffset() const; // abs. max. possible offset std::streamsize offset() const; // current abs. offset std::streamsize eos() const; // abs. offset just past // block[blockIdx()] size_t blockIdx() const; size_t blockOffset() const; // returns -1 if inaccessible std::ios::pos_type seek(std::ios::off_type offset, std::ios::seekdir way = std::ios::beg); void operator++(); // caller must have locked the shared // data void operator+=(size_t len); // caller must have locked the shared // data private: std::ostream &insert(std::ostream &out) const; size_t segmentSize() const; void update(); std::streamsize nReadable() const; }; #include "atmaxoffset.f" #include "blockidx.f" #include "blockoffset.f" #include "eof.f" #include "eos.f" #include "maxoffset.f" #include "nreadable.f" #include "offset.f" #include "operatorinsert.f" #include "segmentsize.f" } // FBB #endif bobcat-3.19.01/sharedsegment/0000755000175000017500000000000012257325714014744 5ustar frankfrankbobcat-3.19.01/sharedsegment/operatorindex.f0000644000175000017500000000012712242371061017764 0ustar frankfrankinline SharedBlock &SharedSegment::operator[](size_t idx) { return d_block[idx]; } bobcat-3.19.01/sharedsegment/clear.cc0000644000175000017500000000043712241415122016327 0ustar frankfrank#include "sharedsegment.ih" void SharedSegment::clear() { d_nReadable = 0; for (auto &block: ranger(d_block, d_block + d_nBlocks)) { int id = block.id(); if (id != -1) { deleteSegment(id); block.setID(-1); } } } bobcat-3.19.01/sharedsegment/newdata.cc0000644000175000017500000000025012241424441016661 0ustar frankfrank#include "sharedsegment.ih" int SharedSegment::newData(size_t idx) { int id = newSegment(d_segmentSize, d_access); d_block[idx].setID(id); return id; } bobcat-3.19.01/sharedsegment/detach.f0000644000175000017500000000021512242371027016331 0ustar frankfranktemplate Type *SharedSegment::detach(Type *sharedPtr, bool requireOK) { rawDetach(sharedPtr, requireOK); return 0; } bobcat-3.19.01/sharedsegment/updatenreadable.cc0000644000175000017500000000033012241361562020361 0ustar frankfrank#include "sharedsegment.ih" void SharedSegment::updateNreadable(streamsize offset) { d_nReadableMutex.lock(); if (offset > d_nReadable) d_nReadable = offset; d_nReadableMutex.unlock(); } bobcat-3.19.01/sharedsegment/create.cc0000644000175000017500000000064012241430776016514 0ustar frankfrank#include "sharedsegment.ih" SharedSegment *SharedSegment::create(int *id, size_t nBlocks, size_t segmentSize, size_t access) { *id = newSegment(segmentSize, access); SharedSegment *segmentPtr = static_cast(attach(*id)); new (segmentPtr) SharedSegment(access, nBlocks, segmentSize); return segmentPtr; } bobcat-3.19.01/sharedsegment/insert.cc0000644000175000017500000000162212241361562016552 0ustar frankfrank#include "sharedsegment.ih" ostream &SharedSegment::insert(ostream &out) const { out << "Access mode: 0" << oct << d_access << dec << "\n" "Information readable until offset " << d_nReadable << "\n" "Size of the data segments: " << d_segmentSize << " bytes\n" << d_nBlocks << " data segments may be defined, " "with a total capacity of " << static_cast(d_segmentSize) * d_nBlocks / 1024 << "kB"; bool firstBlock = true; for (size_t idx = 0; idx != d_nBlocks; ++idx) { if (d_block[idx].id() != -1) { if (firstBlock) { firstBlock = false; out << "\n" "ID(s) of data segments:"; } out << "\n" " at idx " << idx << ": id = " << d_block[idx].id(); } } return out; } bobcat-3.19.01/sharedsegment/segmentsize.f0000644000175000017500000000011712242371336017442 0ustar frankfrankinline size_t SharedSegment::segmentSize() const { return d_segmentSize; } bobcat-3.19.01/sharedsegment/lock.f0000644000175000017500000000011112242371105016021 0ustar frankfrankinline void SharedSegment::lock(size_t idx) { d_block[idx].lock(); } bobcat-3.19.01/sharedsegment/sharedsegment1.cc0000644000175000017500000000102312241361562020153 0ustar frankfrank#include "sharedsegment.ih" SharedSegment::SharedSegment(size_t access, size_t nBlocks, size_t segmentSize) : d_access(access), d_segmentSize(segmentSize), d_nReadable(0), d_nBlocks(nBlocks) { // initialize the data-table. d_block[0] already has // been initialized as `SharedBlock d_block[1]' for ( SharedBlock *begin = d_block + 1, *end = d_block + d_nBlocks; begin != end; ++begin ) new (begin) SharedBlock; } bobcat-3.19.01/sharedsegment/deletesegment.cc0000644000175000017500000000032612241424623020071 0ustar frankfrank#include "sharedsegment.ih" void SharedSegment::deleteSegment(int id) { struct shmid_ds buf; if (shmctl(id, IPC_RMID, &buf) != 0) throw Exception() << "Could not discard shared segment " << id; } bobcat-3.19.01/sharedsegment/nblocks.f0000644000175000017500000000010712242371264016537 0ustar frankfrankinline size_t SharedSegment::nBlocks() const { return d_nBlocks; } bobcat-3.19.01/sharedsegment/nreadable.f0000644000175000017500000000012412242371237017020 0ustar frankfrankinline std::streamsize SharedSegment::nReadable() const { return d_nReadable; } bobcat-3.19.01/sharedsegment/sharedsegment.ih0000644000175000017500000000024712242370763020120 0ustar frankfrank#include "sharedsegment" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/sharedsegment/attach.cc0000644000175000017500000000036112241425172016507 0ustar frankfrank#include "sharedsegment.ih" void *SharedSegment::attach(int id) { void *ret = shmat(id, 0, 0); if (ret == reinterpret_cast(-1)) throw Exception() << "Can't attach shared segment segment" << id; return ret; } bobcat-3.19.01/sharedsegment/newsegment.cc0000644000175000017500000000106612241430576017426 0ustar frankfrank#include "sharedsegment.ih" int SharedSegment::newSegment(size_t requestedSize, size_t access) { int id = shmget(IPC_PRIVATE, requestedSize, access); if (id == -1) // no block available throw Exception() << "Cannot create a shared segment segment"; size_t actualSize = size(id); if (actualSize != requestedSize) throw Exception() << "Incorrect size (" << actualSize << ", should be: " << requestedSize << ") of shared segment"; return id; } bobcat-3.19.01/sharedsegment/nreadablelock.f0000644000175000017500000000011412242371163017666 0ustar frankfrankinline void SharedSegment::nReadableLock() { d_nReadableMutex.lock(); } bobcat-3.19.01/sharedsegment/unlock.f0000644000175000017500000000011512242371130016366 0ustar frankfrankinline void SharedSegment::unlock(size_t idx) { d_block[idx].unlock(); } bobcat-3.19.01/sharedsegment/sharedsegment0000644000175000017500000000623112244427062017515 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SHAREDSEGMENT_ #define INCLUDED_BOBCAT_SHAREDSEGMENT_ #include #include namespace FBB { class SharedSegment { friend std::ostream &operator<<(std::ostream &out, SharedSegment const &sharedData); size_t d_access; size_t d_segmentSize; SharedMutex d_nReadableMutex; std::streamsize d_nReadable; // number of readable characters // (just beyond offset of last character // ever written) size_t d_nBlocks; SharedBlock d_block[1]; // Mutexes and IDs of shared data blocks // in fact SharedBlock block[nBlocks] public: SharedSegment(SharedSegment const &other) = delete; SharedSegment &operator=(SharedSegment const &rhs) = delete; int newData(size_t idx); void lock(size_t idx); void unlock(size_t idx); void nReadableLock(); void nReadableUnlock(); void updateNreadable(std::streamsize offset); std::streamsize nReadable() const; size_t nBlocks() const; size_t segmentSize() const; void clear(); // clear all data, nReadable = 0 size_t access() const; SharedBlock &operator[](size_t idx); static SharedSegment *create(int *id, size_t nBlocks, size_t segmentSize, size_t access); static void deleteSegment(int id); // delete shared segment `id' // attach/detach refer to the mapping // on the current process's memory space static void *attach(int id); template static Type *detach(Type *sharedPtr, bool requireOK = true); // if sharedPtr != 0 the shared // segment is detached. throws // exception if requireOK == true // but detaching fails. // always returns 0 static size_t size(int id); // size of shared data segment id private: SharedSegment(size_t access, size_t nBlocks, size_t segmentSize); std::ostream &insert(std::ostream &out) const; static void rawDetach(void *sharedPtr, bool requireOK); // detaches // throws exception if // requireOK == true // but detaching fails // returns the ID of new shared memory static int newSegment(size_t segmentSize, size_t access); }; #include "access.f" #include "detach.f" #include "lock.f" #include "nblocks.f" #include "nreadable.f" #include "nreadablelock.f" #include "nreadableunlock.f" #include "operatorindex.f" #include "operatorinsert.f" #include "segmentsize.f" #include "unlock.f" } // FBB #endif bobcat-3.19.01/sharedsegment/size.cc0000644000175000017500000000044612242077334016225 0ustar frankfrank#include "sharedsegment.ih" size_t SharedSegment::size(int id) { struct shmid_ds buf; if (shmctl(id, IPC_STAT, &buf) == -1) throw Exception() << "Can't determine segment size of segment " << id << ": " << errnodescr; return buf.shm_segsz; } bobcat-3.19.01/sharedsegment/nreadableunlock.f0000644000175000017500000000012012242371210020217 0ustar frankfrankinline void SharedSegment::nReadableUnlock() { d_nReadableMutex.unlock(); } bobcat-3.19.01/sharedsegment/rawdetach.cc0000644000175000017500000000036512241424101017200 0ustar frankfrank#include "sharedsegment.ih" void SharedSegment::rawDetach(void *sharedPtr, bool requireOK) { if (sharedPtr == 0 || shmdt(sharedPtr) == 0) return; if (requireOK) throw Exception() << "Failed to detach shared segment"; } bobcat-3.19.01/sharedsegment/operatorinsert.f0000644000175000017500000000023412242371362020164 0ustar frankfrankinline std::ostream &operator<<(std::ostream &out, SharedSegment const &sharedData) { return sharedData.insert(out); } bobcat-3.19.01/sharedsegment/access.f0000644000175000017500000000010512242371306016340 0ustar frankfrankinline size_t SharedSegment::access() const { return d_access; } bobcat-3.19.01/sharedstream/0000755000175000017500000000000012257325714014575 5ustar frankfrankbobcat-3.19.01/sharedstream/sharedstream0000644000175000017500000000233312244427062017176 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SHAREDSTREAM_ #define INCLUDED_BOBCAT_SHAREDSTREAM_ #include #include #include namespace FBB { struct SharedStream: private SharedStreambuf, public std::istream, public std::ostream, public virtual SharedEnum__ { SharedStream(); SharedStream( // 2 size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::in | std::ios::out, size_t access = 0600); SharedStream( // 3 int id, std::ios::openmode openMode = std::ios::in | std::ios::out); void open( size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode = std::ios::in | std::ios::out, size_t access = 0600); void open( int id, std::ios::openmode openMode = std::ios::in | std::ios::out); void memInfo(std::ostream &out, char const *end = "\n") const; void clear(); using SharedStreambuf::id; using SharedStreambuf::remove; using SharedStreambuf::kill; }; #include "clear.f" } // FBB #endif bobcat-3.19.01/sharedstream/open2.cc0000644000175000017500000000024712240156366016127 0ustar frankfrank#include "sharedstream.ih" void SharedStream::open(int id, std::ios::openmode openMode) { setMemory(SharedMemory(id)); setOpenMode(openMode); clear(); } bobcat-3.19.01/sharedstream/sharedstream2.cc0000644000175000017500000000044412240137240017635 0ustar frankfrank#include "sharedstream.ih" SharedStream::SharedStream( size_t maxSize, SharedMemory::SizeUnit sizeUnit, std::ios::openmode openMode, size_t access) : SharedStreambuf(maxSize, sizeUnit, openMode, access), std::istream(this), std::ostream(this) {} bobcat-3.19.01/sharedstream/meminfo.cc0000644000175000017500000000026412240714360016527 0ustar frankfrank#include "sharedstream.ih" void SharedStream::memInfo(std::ostream &out, char const *end) const { static_cast(this)->memInfo(out); out << end; } bobcat-3.19.01/sharedstream/clear.f0000644000175000017500000000013412242143611016014 0ustar frankfrankinline void SharedStream::clear() { std::istream::clear(); std::ostream::clear(); } bobcat-3.19.01/sharedstream/open1.cc0000644000175000017500000000041112240156500016105 0ustar frankfrank#include "sharedstream.ih" void SharedStream::open( size_t maxSize, SizeUnit sizeUnit, std::ios::openmode openMode, size_t access) { setMemory(SharedMemory(maxSize, sizeUnit, access)); setOpenMode(openMode); clear(); } bobcat-3.19.01/sharedstream/driver/0000755000175000017500000000000012242406170016056 5ustar frankfrankbobcat-3.19.01/sharedstream/driver/build0000755000175000017500000000111412242406161017100 0ustar frankfrank#!/bin/bash sed 's??"../sharedstream"?' driver.cc > localdriver.cc for x in sharedstream sharedmutex sharedstreambuf sharedmemory \ sharedpos sharedsegment do echo $x cd ../../$x g++ --std=c++11 -Wall -pthread -c *.cc cd ../sharedstream/driver done echo driver g++ -o driver --std=c++11 -Wall localdriver.cc ../../shared*/*.o \ -lpthread -lbobcat rm ../../shared*/*.o localdriver.cc echo Start ./driver for an interactive menu. echo Optionally remove ./driver after the demo-run bobcat-3.19.01/sharedstream/driver/driver0000755000175000017500000016733012242406151017310 0ustar frankfrankELFР4lž4 (44€4€444€€¡š¡š¤š¤*¤*xØ´š´*´*HHHDDPåtd¤x¤ø¤ø||Qåtd/lib/ld-linux.so.2GNU GNUðwð¤H81ýÈuŒÆ(,™ˆÊ$%C %âH€’A€CD€@¬Q Œ@ R&D`  AÆ CDFIJKMQRUWZ\^_abdegijlmnort#4"3^ØUYÃî;ÊNǺge¸IA,öí›Q/È ÒëÓï»bî˜0Üxî?žs–;™º¢\¿Hy˜ CÿJ†”Þ‰•%Á¾ о÷Ηoâjƒ’_qIØÈîUâqo‘ÈÜp4&%ÉÂ" šÀ "9 ¡‰Ñ&" Î @-,!¥Dî… ŸšpŸ×  .,!Ûà.«ÉÓ¼" €œ[À-ŒI@ŸˆiÛ¼" ¶¿¯¼" Œ -!d‚ȼ" Оè^¯Y" e€- !f0œ*AÕ¾" =»Ö¼" !ÿÕ¼" ¹ `ŸC-!Ǽ" Å °žNð›Ç0ë -÷ |/~0ŸŽ dî9 °^¯Y" Ó¯Ñ&" ô L.!ä -Óʼ" p/!   Þ…Ô¼" Êμ" … Pœ””› û €.!libpthread.so.0_ITM_deregisterTMCloneTable_Jv_RegisterClasses_ITM_registerTMCloneTablepthread_mutex_unlockpthread_mutex_lockpthread_mutexattr_init__pthread_key_createpthread_mutexattr_setpsharedpthread_mutex_initlibbobcat.so.3__gmon_start___ZN3FBBlsIcEEONS_9ExceptionES2_RKT__ZN3FBBlsIA14_cEEONS_9ExceptionES3_RKT__ZN3FBB10errnodescrERSo_ZN3FBBlsIA3_cEEONS_9ExceptionES3_RKT__ZN3FBBlsIA41_cEEONS_9ExceptionES3_RKT__ZN3FBB9ExceptionC1ERKS0__ZN3FBBlsIA34_cEEONS_9ExceptionES3_RKT__ZN3FBBlsIiEEONS_9ExceptionES2_RKT__ZN3FBBlsIA9_cEEONS_9ExceptionES3_RKT__ZN3FBBlsIA20_cEEONS_9ExceptionES3_RKT__ZTIN3FBB9ExceptionE_ZN3FBBlsIFRSoS1_EEEONS_9ExceptionES4_RKT__fini_ZN3FBBlsIA39_cEEONS_9ExceptionES3_RKT__ZSt3octRSt8ios_base_ZN3FBB9ExceptionC2ERKS0__ZN3FBBlsIA36_cEEONS_9ExceptionES3_RKT__ZN3FBBlsIjEEONS_9ExceptionES2_RKT__ZN3FBB9ExceptionD1Ev_ZN3FBBlsIA22_cEEONS_9ExceptionES3_RKT__ZTVN3FBB9ExceptionE_ZSt3decRSt8ios_base_ZN3FBBlsIA24_cEEONS_9ExceptionES3_RKT__ZN3FBBlsIA17_cEEONS_9ExceptionES3_RKT_libstdc++.so.6_ZNSo5seekpESt4fposI11__mbstate_tE__cxa_free_exception_ZNSsC1ERKSs_ZNSo3putEc_ZNSt15basic_streambufIcSt11char_traitsIcEE5imbueERKSt6locale_ZNSi5seekgESt4fposI11__mbstate_tE_ZTv0_n12_NSiD0Ev_ZNSt9basic_iosIcSt11char_traitsIcEEC2Ev_ZNSoD0Ev_ZTISt15basic_streambufIcSt11char_traitsIcEE_ZTv0_n12_NSiD1Ev_ZNKSi6gcountEv_ZSt4cout__cxa_allocate_exception_ZNSoD1Ev_ZNSt15basic_streambufIcSt11char_traitsIcEEC2Ev_ZNSsC1Ev_ZStrsIcSt11char_traitsIcEERSt13basic_istreamIT_T0_ES6_RS3__ZNSoD2Ev_ZNSolsEd_ZNSt15basic_streambufIcSt11char_traitsIcEE4syncEv_ZNSolsEi_ZNSolsEj_ZNSt9exceptionD2Ev_ZNSolsEx_ZNSo5tellpEv_ZNSt9basic_iosIcSt11char_traitsIcEE5clearESt12_Ios_Iostate_ZNKSt19basic_ostringstreamIcSt11char_traitsIcESaIcEE3strEv_ZNKSt9basic_iosIcSt11char_traitsIcEEntEv_ZNSoC2EPSt15basic_streambufIcSt11char_traitsIcEE_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc_ZNSiC2EPSt15basic_streambufIcSt11char_traitsIcEE_ZNSt8ios_base4InitC1Ev_ZSt3cin_ZNSt9basic_iosIcSt11char_traitsIcEED2Ev_ZNSolsEPFRSt8ios_baseS0_E_ZNSo5writeEPKci_ZNSiD0Ev_ZTVSt9exception_ZNSt15basic_streambufIcSt11char_traitsIcEED2Ev__cxa_throw_ZNSsD1Ev_ZNSiD1Ev_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c_ZNSolsEPKv_ZNSspLERKSs_ZNKSs6lengthEv_ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEEC1ESt13_Ios_Openmode_ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev_ZTv0_n12_NSoD0Ev_ZNSiD2Ev_ZNSi4readEPci_ZdlPv_ZNKSs4dataEv_ZTv0_n12_NSoD1Ev_ZTVN10__cxxabiv121__vmi_class_type_infoE_ZNSi5tellgEv_ZNSt8ios_base4InitD1Ev_ZNSt15basic_streambufIcSt11char_traitsIcEE6setbufEPci_ZNSirsERi_ZNSolsEPFRSoS_E_ZNSirsERx_ZNSt15basic_streambufIcSt11char_traitsIcEE5uflowEv__gxx_personality_v0_ZTVN10__cxxabiv117__class_type_infoE_ZTISi_ZTISo_ZSt7getlineIcSt11char_traitsIcESaIcEERSt13basic_istreamIT_T0_ES7_RSbIS4_S5_T1_Elibm.so.6sqrtceillibgcc_s.so.1_Unwind_Resumelibc.so.6_IO_stdin_usedshmgetshmatshmctlshmdt__cxa_atexitmemsetmemcpy__libc_start_main_edata__bss_start_endGCC_3.0GLIBC_2.0GLIBC_2.2GLIBC_2.1.3CXXABI_1.3GLIBCXX_3.4   g  P&y ü S  ii  0ii  ii  „ @si  ii  ii  Ó¯k$ t)’/ Ä+; -W@-K€-[-aÀ-SL.m€.v .Oà.Pp/pÔ+Ø+Ü+dà+ä+è+ì+\ð+ô+tø+ü+,R, , , , , ,,C ,$,(,j,,e0,4,8,<,@,D,H,L,P,T,X,\,`,d,h,l, p,!t,#x,$|,%€,&„,'ˆ,(Œ,c,)”,Y˜,*œ,+ ,,¤,M¨,-¬,h°,T´,.¸,`¼,NÀ,/Ä,0È,1Ì,2Ð,3Ô,4Ø,5Ü,7à,8ä,Iè,9ì,:ð,;ô,<ø,>ü,?-@-A-q -B-HSƒìècÃ+‹ƒüÿÿÿ…Àt莃Ä[Ãÿ5Ì+ÿ%Ð+ÿ%Ô+héàÿÿÿÿ%Ø+héÐÿÿÿÿ%Ü+héÀÿÿÿÿ%à+hé°ÿÿÿÿ%ä+h é ÿÿÿÿ%è+h(éÿÿÿÿ%ì+h0é€ÿÿÿÿ%ð+h8épÿÿÿÿ%ô+h@é`ÿÿÿÿ%ø+hHéPÿÿÿÿ%ü+hPé@ÿÿÿÿ%,hXé0ÿÿÿÿ%,h`é ÿÿÿÿ%,hhéÿÿÿÿ% ,hpéÿÿÿÿ%,hxéðþÿÿÿ%,h€éàþÿÿÿ%,hˆéÐþÿÿÿ%,héÀþÿÿÿ% ,h˜é°þÿÿÿ%$,h é þÿÿÿ%(,h¨éþÿÿÿ%,,h°é€þÿÿÿ%0,h¸épþÿÿÿ%4,hÀé`þÿÿÿ%8,hÈéPþÿÿÿ%<,hÐé@þÿÿÿ%@,hØé0þÿÿÿ%D,hàé þÿÿÿ%H,hèéþÿÿÿ%L,hðéþÿÿÿ%P,høéðýÿÿÿ%T,héàýÿÿÿ%X,héÐýÿÿÿ%\,héÀýÿÿÿ%`,hé°ýÿÿÿ%d,h é ýÿÿÿ%h,h(éýÿÿÿ%l,h0é€ýÿÿÿ%p,h8épýÿÿÿ%t,h@é`ýÿÿÿ%x,hHéPýÿÿÿ%|,hPé@ýÿÿÿ%€,hXé0ýÿÿÿ%„,h`é ýÿÿÿ%ˆ,hhéýÿÿÿ%Œ,hpéýÿÿÿ%,hxéðüÿÿÿ%”,h€éàüÿÿÿ%˜,hˆéÐüÿÿÿ%œ,héÀüÿÿÿ% ,h˜é°üÿÿÿ%¤,h é üÿÿÿ%¨,h¨éüÿÿÿ%¬,h°é€üÿÿÿ%°,h¸épüÿÿÿ%´,hÀé`üÿÿÿ%¸,hÈéPüÿÿÿ%¼,hÐé@üÿÿÿ%À,hØé0üÿÿÿ%Ä,hàé üÿÿÿ%È,hèéüÿÿÿ%Ì,hðéüÿÿÿ%Ð,høéðûÿÿÿ%Ô,héàûÿÿÿ%Ø,héÐûÿÿÿ%Ü,héÀûÿÿÿ%à,hé°ûÿÿÿ%ä,h é ûÿÿÿ%è,h(éûÿÿÿ%ì,h0é€ûÿÿÿ%ð,h8épûÿÿÿ%ô,h@é`ûÿÿÿ%ø,hHéPûÿÿÿ%ü,hPé@ûÿÿÿ%-hXé0ûÿÿÿ%-h`é ûÿÿÿ%-hhéûÿÿÿ% -hpéûÿÿÿ%-hxéðúÿÿ1í^‰áƒäðPTRh@îhÐíQVhÍ¡è¿üÿÿôfffffff‹$Ãffffff¸---ƒøwø…ÀtöU‰åƒìÇ$-ÿÐÉö¸---Áø‰ÂÁêÐÑøuú…ÒtöU‰åƒì‰D$Ç$-ÿÒÉÉö¼'€=x/uU‰åƒìè|ÿÿÿÆx/ÉóÃf¡°*…Àt¸…ÀtU‰åƒìÇ$°*ÿÐÉéyÿÿÿésÿÿÿL$ƒäðÿqüU‰åWVSQìÈ…Lþÿÿ‰$è?Ç…TÿÿÿÿÿÿÿÇD$lîÇ$À-èÐûÿÿ…Sÿÿÿ‰D$Ç$à.èjüÿÿ¶…Sÿÿÿ¾ØÇD$ðÇ$À-èœûÿÿ‰\$‰$èàûÿÿÇD$ ‰$èÐûÿÿ…Lþÿÿ‰$èP ¶…Sÿÿÿ¾ÀƒèKƒø,‡„ ‹…<ñÿàÇD$Ç$èÁ ÇD$€‰D$ ÇD$ ÇD$…Lþÿÿ‰$èo;…Lþÿÿ‰$è£ ‰…Tÿÿÿ‹TÿÿÿÇD$ ðÇ$À-èçúÿÿ‰\$‰$è›üÿÿÇD$ ‰$èûÿÿÇD$&ðÇD$À-…Lþÿÿ‰$è£:ÇD$ Ç$À-èéúÿÿé÷ ‹…TÿÿÿƒøÿuÇD$(ðÇ$À-èuúÿÿéÓ ‹TÿÿÿÇD$;ðÇ$À-èVúÿÿ‰\$‰$è üÿÿÇD$ ‰$èŠúÿÿ¶…Sÿÿÿôÿÿ‰Ã…@ÿÿÿ‰$èòÿÿ‰\$‰D$…LþÿÿƒÀX‰$èÕóÿÿ…LþÿÿƒÀ\‰$è4ðÿÿ„ÀtÇD$øðÇ$À-èlñÿÿëhEÀ•LþÿÿƒÂX‰T$‰$èâðÿÿƒì…0ÿÿÿ‰D$EÀ‰$è‰Ã‰ÖÇD$ñÇ$À-è"ñÿÿ‰\$‰t$‰$èðÿÿÇD$²ð‰$èñÿÿ…@ÿÿÿ‰$èòÿÿëU»…Lþÿÿ‰$èÛ‰Øéä¶…Sÿÿÿ¾ØÇD$ ñÇ$À-èºðÿÿ‰\$‰$èþðÿÿÇD$ ‰$èîðÿÿé´ôÿÿ‰Æ…Xÿÿÿ‰$è˜îÿÿë‰Æ‰$èìïÿÿ‰ðëhëfëd‰ÆE€‰$èwîÿÿë‰Æ‰$èËïÿÿ‰ðëëë‹¥Dþÿÿë;‰ÆE¨‰$èNîÿÿë‰Æ‰$è¢ïÿÿ‰óë ‰Ãë‰Ãë‰Ã…@ÿÿÿ‰$è6ñÿÿ‰Øëë‰Ã…Lþÿÿ‰$èü‰Øë‰$èòÿÿeðY[^_]aüÃU‰åƒìƒ}u1} ÿÿu(Ç$y/èÇðÿÿÇD$-ÇD$y/Ç$  è ïÿÿÉÃU‰åƒìÇD$ÿÿÇ$è§ÿÿÿÉÃU‰å‹Eǘ-]ÃU‰å‹U‹E Ð]ÃU‰å‹E‹@]ÃU‰åƒì‹EƒÀ(‰$èàÿÿÿÉÃU‰åƒì‹EƒÀ(‰$è€ ÉÃU‰åƒì‹EƒÀ(‰$èDÉÃU‰åƒì‹E‹ƒè‹‰Â‹EÐÇD$‰$è›ðÿÿ‹E‹ƒè‹‰Â‹EÐÇD$‰$èzðÿÿÉÃU‰åSƒì‹E‰$è:ÿÿÿ‹EÇ(-‹EƒÀ‰$èOîÿÿë‰Ã‹E‰$èððÿÿ‰Ø‰$è¦ðÿÿƒÄ[]ÃU‰å‹Eǘ-]ÃU‰åSƒì‹U ‹E‰T$‰$èÙÿÿÿ‹EÇ(-‹E P‹EƒÀ‰T$‰$èHíÿÿë‰Ã‹E‰$è‰ðÿÿ‰Ø‰$è?ðÿÿƒÄ[]ÃU‰å‹E]ÃU‰åSìÔÇD$…@ÿÿÿ‰$èAïÿÿ‹E ‰D$…@ÿÿÿ‰$èìíÿÿEô•@ÿÿÿ‰T$‰$è·ïÿÿƒì‹EPEô‰D$‰$è¿ëÿÿEô‰$èÔîÿÿ‹E‰$è€ÿÿÿ‰Ã…@ÿÿÿ‰$è)ðÿÿ‰Øë+‰ÃEô‰$è¨îÿÿë‰Ã…@ÿÿÿ‰$èðÿÿ‰Øë‰$èzïÿÿ‹]üÉÃU‰åƒì‹E ‰Eø‹E‰Eü‹M‹Eø‹Uü‰‰Q‹EÇ@‹EÇ@ ÉÃU‰å‹E‹P‹]ÃU‰åS‹E‹P‹‹M ‹Y‹ )ÈÚ[]ÃU‰åƒìºò‹E‰ºTò‹E‰PPº\‹E¸|ò‰ºhò‹E‰PX¸°ò‹UƒÂX‰D$‰$è¦ìÿÿ¸¨ò‹UƒÂP‰D$‰$èoëÿÿº¤ò‹E‰T$‰$è4¸…Àt‹EƒÀ\‰$è”îÿÿ¸…Àt ‹E‰$èìÿÿÉËD$‹Aô‰D$éHÿÿÿƒl$Xé>ÿÿÿƒl$Pé4ÿÿÿU‰åƒì‹E‰$è#ÿÿÿ‹E‰$èÌëÿÿÉËD$‹Aô‰D$ëÓƒl$Xë̃l$PëÅU‰åƒì‹E‹@$…Àu¸ëj‹EƒÀ ‰$è±;E ”À„Àt¸ëK‹EƒÀ ‰$è’‹U‹R‰D$‰$èV‹EÇ@ ‹E‹@$ÇD$‰$èl‹U‰B$¸ÉÃU‰åƒì‹E‰$èGëÿÿÉÃU‰åƒì‹E‰$èÛÿÿÿÉÃU‰åƒì‹E ÁàÅ)ƒ ‹EЃÀ‰$èÄÿÿÿÉÃU‰å‹E‹@ ]ÃU‰åƒì‹E ˆEô¶Eô‰D$‹E‰$è“$¸ÉÃU‰åƒì‹E‰$赋E‰$è‹E‰$èå ÉÃU‰åƒì‹E‹@‹UƒÂ ‰D$‰$è6‹EÇ@ ‹E‹@$ÇD$‰$èrÿÿÿ‹U‰B$ÉÃU‰åƒìH‹E ‰EЋE‰EÔ‹M‹EЋUÔ¥ÂÓàöÁ t‰Â1À‰EЉUÔÝ ôÝ]ð¸(º‰EȉUÌßmÈÙàÝ(ôÞÉÝ0ôÞùÝ]è‹EЋUÔ÷؃Ò÷Ú‰EȉUÌßmÈÝ]àÝEèÜMèÝEðÝ8ôÞÉÜMàÞéÝ$èêÿÿÜeèÝEðØÀÞùÝ$è{ìÿÿÙ}Æ·EÆ´ f‰EÄÙmÄß}ÈÙmÆ‹EÈ‹ỦEÜ‹EÜÁà ‰EغØÿÿÿ‹EØÐÁèº%I’$÷â‹E‰‹EØÉÃU‰åƒì‹E ‹‹E‰‹E‹@$ÇD$‰$èTþÿÿ‹E‹@ÇD$‰$è@ÉÃU‰åƒìºTô‹E‰‹E‹@$ÇD$‰$èþÿÿ‹E‹@ÇD$‰$èÉÃU‰åƒì‹E ˆEô¶Eô‰D$‹E‰$è‘"¸ÉÃU‰åƒì(‹E‰$è#‹EƒÀ ‰$è{„Àt ÇEôÿÿÿÿë\‹EƒÀ ‰$è’ýÿÿ‰D$‹E‰$è‹E‰$è¶¾À‰Eô‹EƒÀ ‰$èï‹EƒÀ ‰$èSýÿÿ‰D$‹E‰$è2 ‹EôÉÃU‰å‹E‹@ ]ÃU‰åSƒì‹E‹X‹E‹‰$èÚÿÿÿ9ÃÀƒÄ[]ÃU‰åVSƒì‹E‹@…ÀuÇD$‘ô‹E ‰$è èÿÿéì‹E‹XÇD$©ô‹E ‰$èïçÿÿ‰\$‰$è£éÿÿÇD$ ‰$è#èÿÿ‹E‹@$…ÀuÇD$Èô‹E ‰$è¶çÿÿëa‹EƒÀ ‰$è€üÿÿ‰Ã‹E‹p$ÇD$ðô‹E ‰$è‹çÿÿ‰t$‰$èÿæÿÿÇD$õ‰$èoçÿÿ‰\$‰$è#èÿÿÇD$ ‰$è£çÿÿ‹EX ‹E‹@‰D$‹E ‰$è#ÇD$ ‰$èxçÿÿ‰\$‰$è!ƒÄ[^]ÃU‰åƒì‹E‰D$‹E ‰$èïÉÃU‰åƒì‹E‰D$‹E ‰$è¡ ÉÃU‰åƒì‹E‰$èüÿÿ‹E‹@‰$è#‹E‹@ÇD$‰$è“ýÿÿ‹U‰BÉÃU‰åƒì‹E‹@ …Àu‹E‹@‹U ‰T$‰$è%‹E‹@ P‹E‰P ÉÃU‰åƒì‹E‰$èq ÉÃU‰åƒì‹E ÁàÅ)ƒ ‹EЃÀ‰$èÄÿÿÿÉÃU‰åƒì(ÇEô‹E‹@‰$è3‰Eðë‹Eô‰D$‹E‰$èZÿÿÿƒEô‹Eô;Eðuâ‹E‹@‰$èÉÃU‰å‹E‹@$]ÃU‰åƒì‹EƒÀ‰$èÖ ÉÃU‰åƒì(‹EƒÀ ‰$è„úÿÿ‰Eô‹Eô‰D$‹E‰$è™ùÿÿƒð„Àt‹Eô‰D$‹E‰$èÉÃU‰åƒì(‹E‹@‹U ‰T$‰$觉$蓉Eôƒ}ôÿ”ÀˆEó€}ót-‹E‹@‹U ‰T$‰$è×þÿÿ‹E‹@‹U ‰T$‰$è‰Eô‹Eô‰$è,‹U‰B$€}ót:‹Eô‰$è…!‹U‹R$‰D$ÇD$‰$èKæÿÿ‹E‹@‹U ‰T$‰$èvùÿÿÉÃU‰å‹E‹@]ÃU‰å‹E ÁàÅ)ƒ ‹EЃÀ]ÃU‰åSƒì‹EƒÀ ‰$è3„Àt¸ë!‹E‰$è¯þÿÿ‹E‹X$‹EƒÀ ‰$è؃Ä[]ÃU‰å‹E‹P‹E‹@9”À]ÃU‰å‹E‹@]ÃU‰åƒì(‹E‰$è…ÿÿÿ‰Eôƒ}ôu¸ÿÿÿÿëu‹EƒÀ ‰$èÙøÿÿ‰D$‹E‰$èNýÿÿ‹E ‰Â‹Eôˆ‹EƒÀ ‰$è@ ‹EƒÀ ‰$è¤øÿÿ‰D$‹E‰$胋EƒÀ ‰$è‹U‹R‰D$‰$èY#‹E ÉÃU‰å‹E‹@]ÃU‰åƒì(‹EƒÀ ‰$èûÿÿ„Àt¸ÿÿÿÿëo‹EƒÀ ‰$èÇÿÿÿ‰EôëE‹E‰D$‹E ‰D$‹E‰$èE‰Eðƒ}ðÿuë'‹Eð)E‹EðE ‹Eð‹UƒÂ ‰D$‰$èS ƒ}uµ‹EƒÀ ‰$èiÿÿÿ+EôÉÃU‰åSƒì$‹EƒÀ ‰$èúÿÿ„Àt ¸ÿÿÿÿéË‹E‹@‰$èeúÿÿ‰Eð‹E‰$èýüÿÿ‹EƒÀ ‰$賉Eô‹Eð;Eô}‹Eð‰Eô‹EƒÀ ‰$èøþÿÿ‹Uô)‰ЉEì‹Eì;Es‹Eì‰E‹EƒÀ ‰$èB÷ÿÿ‰D$‹E‰$è·ûÿÿ‹E‹X$‹EƒÀ ‰$è þÿÿ‹E‰D$‰T$‹E ‰$è áÿÿ‹EƒÀ ‰$èøöÿÿ‰D$‹E‰$è׋EƒÄ$[]ÃU‰å‹E‹@]ÃU‰åSƒì‹E‰$èÂöÿÿX‹E‰$è ¯ÃƒÄ[]ÃU‰åƒì‹E‹‰$è·ÿÿÿÉÃU‰åƒì‹E‰$è{ûÿÿ‹E‰$è¾úÿÿÉÃU‰åSƒì$‹E‰Eð‹E‰Eô‹E X ‹M‹E‰D$‹Eð‹Uô‰D$‰T$ ‰\$‰ $è+ƒì‹E‹]üÉÂU‰åƒì(‹E ‹‹E‰‹EÇ@ÿÿÿÿ‹EÇ@‹EÇ@ ‹EÇ@‹EÇ@‹EÇ@‹EÇ@‹EÇ@ ‹EÇ@$‹Eº‹M‰L$ ‰D$‰T$Eð‰$èBöÿÿ‰Eô‹Eð‹UJ‹U‰T$ ‹Uô‰T$‰D$‰ $èj‹U‰B‹E‹@‹UƒÂ ‰D$‰$è ë‰$èˆâÿÿÉÃU‰åƒì(‹E‰$è׺Tô‹E‰‹EÇ@ÿÿÿÿ‹EÇ@‹EÇ@ ‹EÇ@‹EÇ@‹EÇ@‹EÇ@‹EÇ@ ‹EÇ@$‹E º‹M‰L$ ‰D$‰T$Eð‰$è[õÿÿ‰Eô‹Eð‹UJ‹U‰T$ ‹Uô‰T$‰D$‰ $胋U‰B‹E‹@‹UƒÂ ‰D$‰$è%ë‰$è¡áÿÿÉÃU‰å]ÃU‰åƒì‹E ‹‹E‰‹E‹U‰P‹E‰$è„ ‹U‰B‹EÇ@ ‹EÇ@‹EÇ@‹EÇ@‹EÇ@‹EÇ@ ‹EÇ@$‹E‹@‹UƒÂ ‰D$‰$èŠÉÃU‰åƒì‹E‰$è_ÿÿÿºTô‹E‰‹E‹U ‰P‹E ‰$èï ‹U‰B‹EÇ@ ‹EÇ@‹EÇ@‹EÇ@‹EÇ@‹EÇ@ ‹EÇ@$‹E‹@‹UƒÂ ‰D$‰$èõÉÃU‰åƒì‹EƒÀ ‰$èüõÿÿ„Àt¸ë‹EƒÀ ‰$è½ÉÃU‰åƒì‹E‹@ …Àt ‹E‹@ Pÿ‹E‰P ‹E‹@ …Àu¸ë¸„Àt‹E‹@‹U ‰T$‰$èšòÿÿÉÃU‰åƒì(ÇEô‹E‹@‰$èí÷ÿÿ‰Eðë‹Eô‰D$‹E‰$è~ÿÿÿƒEô‹Eô;Eðuâ‹E‹@‰$èÉÃU‰åƒì‹EƒÀ‰$èòÿÿÉÃU‰åƒì(‹EƒÀ ‰$è ùÿÿ„Àt ¸ÿÿÿÿé‹EƒÀ ‰$è¾ùÿÿ‰Eôëe‹E‰D$‹E ‰D$‹E‰$èf‰Eðƒ}ðÿuëG‹Eð)E‹EðE ‹Eð‹UƒÂ ‰D$‰$èJ‹EƒÀ ‰$èfùÿÿ‹U‹R‰D$‰$訃}u•‹EƒÀ ‰$è@ùÿÿ+EôÉÃU‰åSƒì$‹EƒÀ ‰$èkøÿÿ„Àt ¸ÿÿÿÿ騋E‰$èäöÿÿ‹EƒÀ ‰$èšúÿÿ‰Ã‹EƒÀ ‰$èîøÿÿ)É؉Eô‹Eô;Es‹Eô‰E‹EƒÀ ‰$è;ñÿÿ‰D$‹E‰$è°õÿÿ‹E‹X$‹EƒÀ ‰$èøÿÿ‹E‰D$‹E ‰D$‰$èÛÿÿ‹EƒÀ ‰$èñðÿÿ‰D$‹E‰$èÐýÿÿ‹EƒÄ$[]ÃU‰åƒì‹E‰$èuðÿÿÉÃU‰åVSƒì ‹E‰$èÜÿÿ…À•À„À„ŒÇ$è~Úÿÿ‰ÃÇEðÇEôEð‰$èËìÿÿÇD$DõEð‰$èY‰D$‰$èíÿÿEð‰$è‰ÙÿÿÇD$ð›ÇD$€-‰$èÝÿÿ‰ÆEð‰$èdÙÿÿë‰Æ‰$è¸Úÿÿ‰ð‰$èNÝÿÿƒÄ [^]ÃU‰åSìÔÇD$…@ÿÿÿ‰$èWÜÿÿ‹E ‰D$…@ÿÿÿ‰$èÛÿÿEô•@ÿÿÿ‰T$‰$èÍÜÿÿƒì‹EPEô‰D$‰$èÕØÿÿEô‰$èêÛÿÿ‹E‰$è–ìÿÿ‰Ã…@ÿÿÿ‰$è?Ýÿÿ‰Øë+‰ÃEô‰$è¾Ûÿÿë‰Ã…@ÿÿÿ‰$èÝÿÿ‰Øë‰$èÜÿÿ‹]üÉÃU‰åƒì(Eô‰$è ÛÿÿÇD$Eô‰$è†Øÿÿ‹EUô‰T$‰$èdÚÿÿÉÃU‰åWVSƒì‹E‰$èïÿÿ‰Ã‹E‹p‹E‹xÇD$zõ‹E ‰$è Úÿÿ‰|$‰$èÁÛÿÿÇD$•õ‰$èñÙÿÿ‰t$‰$è¥ÛÿÿÇD$¨õ‰$èÕÙÿÿ‰\$‰$è‰ÚÿÿƒÄ[^_]ÃU‰åƒì‹E‹@‰Â‹E Љ‹E‰P‹E‰$ènÉÃU‰åƒì‹E‹@P‹E‰P‹E‰$èLÉÃU‰åSƒì‹E‹U ‰‹EÇ@‹E ‰$èróÿÿ‰Ã‹E‰$èu÷ÿÿ¯Ã‰Â‹E‰PƒÄ[]ÃU‰åƒì(‹E‰Eð‹E‰Eôƒ}u‹E ‹@™EðUôëƒ}u‹E ‰$èh™EðUôƒ}ôx,‹E ‹@™;Uô| ;Uô;Eðr‹Uð‹E ‰P‹E ‰$è™ëÇEðÿÿÿÿÇEôÿÿÿÿ‹Eð‹Uô‰D$‰T$‹E‰$è8ëÿÿ‹EÉÂU‰åƒì‹E‹‰$èðÿÿÉÃU‰åƒì(‹E‰$èÙÿÿÿ‰Eð‹E‰$èeöÿÿ‰Eô‹Eô;Eð~‹Eð‰Eô‹E‹@;Eô}‹E‹@‹Uô)‰Ðë¸ÉÃU‰åVSƒì0‹E‹P‹E‹@9ŸÀˆE÷€}÷t‹E‹@‰Eà‹E‹P‹E‰P‹E‰$èöÿÿ‰Eð‹E‹@º÷uð‰Â‹E‰P ‹E‹@º÷uð‹E‰P€}÷„ÔÇ$ègÖÿÿ‰ÃÆEç)‹EpÇEèÇEìEè‰$èªèÿÿÇD$ÅõEè‰$è—Uà‰T$‰$èDÇD$Îõ‰$èò‰t$‰$è(Uç‰T$‰$蓉D$‰$è§èÿÿEè‰$è.ÕÿÿÇD$ð›ÇD$€-‰$è¶Øÿÿ‰ÆEè‰$è Õÿÿ‰ðë‰Æ‰$è[Öÿÿ‰ðë‰$èïØÿÿƒÄ0[^]ÃU‰åSìÔÇD$…@ÿÿÿ‰$èø×ÿÿ‹E ‰D$…@ÿÿÿ‰$è£ÖÿÿEô•@ÿÿÿ‰T$‰$ènØÿÿƒì‹EPEô‰D$‰$èvÔÿÿEô‰$è‹×ÿÿ‹E‰$è7èÿÿ‰Ã…@ÿÿÿ‰$èàØÿÿ‰Øë+‰ÃEô‰$è_×ÿÿë‰Ã…@ÿÿÿ‰$è½Øÿÿ‰Øë‰$è1Øÿÿ‹]üÉÃU‰åSìÔÇD$…@ÿÿÿ‰$è<×ÿÿ‹E ‹‰D$…@ÿÿÿ‰$è¥×ÿÿEô•@ÿÿÿ‰T$‰$è°×ÿÿƒì‹EPEô‰D$‰$è¸ÓÿÿEô‰$èÍÖÿÿ‹E‰$èyçÿÿ‰Ã…@ÿÿÿ‰$è"Øÿÿ‰Øë+‰ÃEô‰$è¡Öÿÿë‰Ã…@ÿÿÿ‰$èÿ×ÿÿ‰Øë‰$ès×ÿÿ‹]üÉÃU‰åSìÔÇD$…@ÿÿÿ‰$è~Öÿÿ‹E ‰D$…@ÿÿÿ‰$è)ÕÿÿEô•@ÿÿÿ‰T$‰$èôÖÿÿƒì‹EPEô‰D$‰$èüÒÿÿEô‰$èÖÿÿ‹E‰$è½æÿÿ‰Ã…@ÿÿÿ‰$èf×ÿÿ‰Øë+‰ÃEô‰$èåÕÿÿë‰Ã…@ÿÿÿ‰$èC×ÿÿ‰Øë‰$è·Öÿÿ‹]üÉÃU‰åSìÔÇD$…@ÿÿÿ‰$èÂÕÿÿ‹E ¶¾À‰D$…@ÿÿÿ‰$è·ÔÿÿEô•@ÿÿÿ‰T$‰$è2Öÿÿƒì‹EPEô‰D$‰$è:ÒÿÿEô‰$èOÕÿÿ‹E‰$èûåÿÿ‰Ã…@ÿÿÿ‰$è¤Öÿÿ‰Øë+‰ÃEô‰$è#Õÿÿë‰Ã…@ÿÿÿ‰$èÖÿÿ‰Øë‰$èõÕÿÿ‹]üÉÃU‰åVSƒì ‹EÇD$ÇD$‰$è}Óÿÿ‰Eôƒ}ôÿuxÇ$èhÒÿÿ‰ÃÇEìÇEðEì‰$èµäÿÿÇD$ìõEì‰$èmU‰T$‰$èOýÿÿ‰D$‰$èÝäÿÿEì‰$èdÑÿÿÇD$ð›ÇD$€-‰$èìÔÿÿ‹Eôë#‰ÆEì‰$è:Ñÿÿë‰Æ‰$èŽÒÿÿ‰ð‰$è$ÕÿÿƒÄ [^]ÃU‰åSìÔÇD$…@ÿÿÿ‰$è-Ôÿÿ‹E ‰D$…@ÿÿÿ‰$èØÒÿÿEô•@ÿÿÿ‰T$‰$è£Ôÿÿƒì‹EPEô‰D$‰$è«ÐÿÿEô‰$èÀÓÿÿ‹E‰$èläÿÿ‰Ã…@ÿÿÿ‰$èÕÿÿ‰Øë+‰ÃEô‰$è”Óÿÿë‰Ã…@ÿÿÿ‰$èòÔÿÿ‰Øë‰$èfÔÿÿ‹]üÉÃU‰åƒì8‹EÇ@ ‹E‹@$ÁàÅ)ƒ ‹EÐH‹EP(E܉L$‰T$‰$考ìE܉Eð‹Eð‰$è’‹‰Eô‹Eð‰$芋‰Eìë<‹Eô‰Eè‹Eè‰$è íÿÿ‰Eäƒ}äÿt‹Eä‰$èÇD$ÿÿÿÿ‹Eè‰$èƒEô‹Eô;Eìu¼ÉÃU‰å‹E‹U ‰P]ÃU‰åƒìE‰D$E ‰D$‹E‰$è‹EÉÂU‰å‹E]ÃU‰å‹EƒÀ]ÃU‰å‹E ‹‹E‰‹E‹‹E‰P]ÃU‰åWVSƒì,‹E‰D$‹E‰$è_‹U‰‹E‹‰$è)ýÿÿ‰Eä‹uä‰t$Ç$DèH‰Ã…Ût‹E‰D$ ‹E ‰D$‹E‰D$‰$èú ‹Eäë‰Ç‰t$‰$è‰ø‰$èÃÒÿÿƒÄ,[^_]ÃU‰å‹E ]ÃU‰å]ÃU‰åVSƒìp‹EUœ‰T$ÇD$‰$èœÏÿÿ…À•À„À„Ç$è#Ïÿÿ‰ÃÇEðÇEôEð‰$èpáÿÿÇD$öEð‰$èjM‰L$‰$è úÿÿ‰D$‰$è˜áÿÿEð‰$èÎÿÿÇD$ð›ÇD$€-‰$è§Ñÿÿ‰ÆEð‰$èúÍÿÿë‰Æ‰$èNÏÿÿ‰ðë‰$èâÑÿÿƒÄp[^]ÃU‰åSìÔÇD$…@ÿÿÿ‰$èëÐÿÿ‹E ‰D$…@ÿÿÿ‰$è–ÏÿÿEô•@ÿÿÿ‰T$‰$èaÑÿÿƒì‹EPEô‰D$‰$èiÍÿÿEô‰$è~Ðÿÿ‹E‰$è*áÿÿ‰Ã…@ÿÿÿ‰$èÓÑÿÿ‰Øë+‰ÃEô‰$èRÐÿÿë‰Ã…@ÿÿÿ‰$è°Ñÿÿ‰Øë‰$è$Ñÿÿ‹]üÉÃU‰åWVSƒì<‹E‹@º‰EЉUÔßmЋE‹@$º‰EЉUÔßmÐÞÉÝ÷ÞùÝ]È‹E‹X$‹E‹p‹E‹x ‹E‹‰EÄÇD$Iö‹E ‰$è£ÎÿÿÇD$¯Ñ‰$èÍÿÿ‹MĉL$‰$èDÏÿÿÇD$‰Ñ‰$èôÌÿÿÇD$Xö‰$èdÎÿÿ‰|$‰$èÐÿÿÇD$|ö‰$èHÎÿÿ‰t$‰$èüÎÿÿÇD$™ö‰$è,Îÿÿ‰\$‰$èàÎÿÿÇD$¤ö‰$èÎÿÿÝEÈÝ\$‰$èqÐÿÿÇD$Ýö‰$èñÍÿÿÆEçÇEà鯋EàÁàÅ)ƒ ‹EЃÀ‰$èûèÿÿƒøÿ•À„Àt€}çtÆEçÇD$àö‹E ‰$è˜Íÿÿ‹EàÁàÅ)ƒ ‹EЃÀ‰$è²èÿÿ‰ÃÇD$ùö‹E ‰$èaÍÿÿ‹Uà‰T$‰$èÎÿÿÇD$÷‰$èBÍÿÿ‰\$‰$èöÎÿÿƒEà‹E‹@$;Eà…Bÿÿÿ‹E ƒÄ<[^_]ÃU‰å‹U‹E !Ð]ÃU‰å‹U‹E Ð]ÃU‰å‹E÷Ð]ÃU‰åƒì‹E‹‹U ‰T$‰$èÏÿÿÿ‹U‰‹EÉÃU‰åƒì‹E‹‹U ‰T$‰$èžÿÿÿ‹U‰‹EÉÃU‰åƒì(‹E‹@ ‰Eô‹E‰$è”ÿÿÿ‹UƒÂ ‰D$‰$è°ÿÿÿ‹E‰D$‹E ‰$èVÿÿÿ‹UƒÂ ‰D$‰$èhÿÿÿ‹EôÉÃU‰åƒìÇD$JÇD$‹E‰$èŠÿÿÿ‹EÉÃU‰åƒìÇD$JÇD$@‹E‰$èdÿÿÿ‹EÉÃU‰åƒì(‹E‹‹E‹@‰T$‰$è1‰Eô‹E ÁàÅ)ƒ ‹EÐP‹Eô‰D$‰$è)úÿÿ‹EôÉÃU‰åVSƒì0‹U ‹E‰T$‰D$Ç$èŠÍÿÿ‰Eôƒ}ôÿuiÇ$èEÊÿÿ‰ÃÇEäÇEèEä‰$è’ÜÿÿÇD$ ÷Eä‰$è@‰D$‰$èÉÜÿÿEä‰$èPÉÿÿÇD$ð›ÇD$€-‰$èØÌÿÿ‹Eô‰$è­‰Eà‹Uà‹E9„§Ç$èÀÉÿÿ‰ÃÇEìÇEðEì‰$è ÜÿÿÇD$G÷Eì‰$èwUà‰T$‰$è$ÇD$X÷‰$èÒM‰L$‰$èÇD$f÷‰$èo‰D$‰$èÜÿÿEì‰$èÈÿÿÇD$ð›ÇD$€-‰$èÌÿÿ‹EôëB‰ÆEä‰$ècÈÿÿë‰Æ‰$è·Éÿÿ‰ðë‰ÆEì‰$èFÈÿÿë‰Æ‰$èšÉÿÿ‰ðë‰$è.ÌÿÿƒÄ0[^]ÃU‰åSìÔÇD$…@ÿÿÿ‰$è7Ëÿÿ‹E ‰D$…@ÿÿÿ‰$èâÉÿÿEô•@ÿÿÿ‰T$‰$è­Ëÿÿƒì‹EPEô‰D$‰$èµÇÿÿEô‰$èÊÊÿÿ‹E‰$èvÛÿÿ‰Ã…@ÿÿÿ‰$èÌÿÿ‰Øë+‰ÃEô‰$èžÊÿÿë‰Ã…@ÿÿÿ‰$èüËÿÿ‰Øë‰$èpËÿÿ‹]üÉÃU‰åSìÔÇD$…@ÿÿÿ‰$è{Êÿÿ‹E ‰D$…@ÿÿÿ‰$è&ÉÿÿEô•@ÿÿÿ‰T$‰$èñÊÿÿƒì‹EPEô‰D$‰$èùÆÿÿEô‰$èÊÿÿ‹E‰$èºÚÿÿ‰Ã…@ÿÿÿ‰$ècËÿÿ‰Øë+‰ÃEô‰$èâÉÿÿë‰Ã…@ÿÿÿ‰$è@Ëÿÿ‰Øë‰$è´Êÿÿ‹]üÉÃU‰åSìÔÇD$…@ÿÿÿ‰$è¿Éÿÿ‹E ‹‰D$…@ÿÿÿ‰$è(ÉÿÿEô•@ÿÿÿ‰T$‰$è3Êÿÿƒì‹EPEô‰D$‰$è;ÆÿÿEô‰$èPÉÿÿ‹E‰$èüÙÿÿ‰Ã…@ÿÿÿ‰$è¥Êÿÿ‰Øë+‰ÃEô‰$è$Éÿÿë‰Ã…@ÿÿÿ‰$è‚Êÿÿ‰Øë‰$èöÉÿÿ‹]üÉÃU‰åSìÔÇD$…@ÿÿÿ‰$èÉÿÿ‹E ‰D$…@ÿÿÿ‰$è¬ÇÿÿEô•@ÿÿÿ‰T$‰$èwÉÿÿƒì‹EPEô‰D$‰$èÅÿÿEô‰$è”Èÿÿ‹E‰$è@Ùÿÿ‰Ã…@ÿÿÿ‰$èéÉÿÿ‰Øë+‰ÃEô‰$èhÈÿÿë‰Ã…@ÿÿÿ‰$èÆÉÿÿ‰Øë‰$è:Éÿÿ‹]üÉÃU‰åSìÔÇD$…@ÿÿÿ‰$èEÈÿÿ‹E ‰D$…@ÿÿÿ‰$èðÆÿÿEô•@ÿÿÿ‰T$‰$è»Èÿÿƒì‹EPEô‰D$‰$èÃÄÿÿEô‰$èØÇÿÿ‹E‰$è„Øÿÿ‰Ã…@ÿÿÿ‰$è-Éÿÿ‰Øë+‰ÃEô‰$è¬Çÿÿë‰Ã…@ÿÿÿ‰$è Éÿÿ‰Øë‰$è~Èÿÿ‹]üÉÃU‰åVSƒì ‹E ˆEäƒ}t‹E‰$èiÄÿÿ…Àu¸ë¸„Àté–€}䄌Ç$èÚÄÿÿ‰ÃÇEðÇEôEð‰$è'×ÿÿÇD$„÷Eð‰$èZ‰D$‰$è^×ÿÿEð‰$èåÃÿÿÇD$ð›ÇD$€-‰$èmÇÿÿ‰ÆEð‰$èÀÃÿÿë‰Æ‰$èÅÿÿ‰ð‰$èªÇÿÿƒÄ [^]ÃU‰åSìÔÇD$…@ÿÿÿ‰$è²Æÿÿ‹E ‰D$…@ÿÿÿ‰$è]ÅÿÿEô•@ÿÿÿ‰T$‰$è(Çÿÿƒì‹EPEô‰D$‰$è0ÃÿÿEô‰$èEÆÿÿ‹E‰$èñÖÿÿ‰Ã…@ÿÿÿ‰$èšÇÿÿ‰Øë+‰ÃEô‰$èÆÿÿë‰Ã…@ÿÿÿ‰$èwÇÿÿ‰Øë‰$èëÆÿÿ‹]üÉÃU‰åWVSƒì,‹E‹U ‰‹E‹U‰P‹EƒÀ‰$è4êÿÿ‹EÇ@ ‹E‹U‰P$‹Ep(»‰÷ë‰<$èâƒÇƒëƒûÿuí‹EƒÀD‰Eä‹E‹@$ÁàÅ)ƒ ‹EЃÀ‰Eàë%‹uä‰t$Ç$èóÿÿ‰Ã…Ût‰$苃Eä‹Eä;EàuÓët‰Ç…öt‰ØkÀä9ót ƒë‰$è~ëï‰ûë9‰Ç‰t$‰$èKóÿÿ‰þ‹EƒÀ(…Àt‹EXD‹EƒÀ(9Ãt ƒë‰$èCëé‰ó‹EƒÀ‰$è·çÿÿ‰Ø‰$è»ÅÿÿƒÄ,[^_]ÃU‰åƒì‹E‰$èéÿÿ‹EÇ@ÿÿÿÿÉÃU‰åƒì‹E‰$èuçÿÿÉÃU‰åVSƒìp‹EUœ‰T$ÇD$‰$ènÂÿÿƒøÿ”À„À„˜Ç$èôÁÿÿ‰ÃÇEðÇEôEð‰$èAÔÿÿÇD$°÷Eð‰$èM‰L$‰$èÛìÿÿÇD$Ù÷‰$è,ÇD$@Ÿ‰$èØ‰D$‰$èIÔÿÿEð‰$èÐÀÿÿÇD$ð›ÇD$€-‰$èXÄÿÿ‹EÀë%‰ÆEð‰$è¦Àÿÿë‰Æ‰$èúÁÿÿ‰ðë‰$èŽÄÿÿƒÄp[^]ÃU‰åSìÔÇD$…@ÿÿÿ‰$è—Ãÿÿ‹E ‰D$…@ÿÿÿ‰$èBÂÿÿEô•@ÿÿÿ‰T$‰$è Äÿÿƒì‹EPEô‰D$‰$èÀÿÿEô‰$è*Ãÿÿ‹E‰$èÖÓÿÿ‰Ã…@ÿÿÿ‰$èÄÿÿ‰Øë+‰ÃEô‰$èþÂÿÿë‰Ã…@ÿÿÿ‰$è\Äÿÿ‰Øë‰$èÐÃÿÿ‹]üÉÃU‰åSìÔÇD$…@ÿÿÿ‰$èÛÂÿÿ‹E ‰D$…@ÿÿÿ‰$è†ÁÿÿEô•@ÿÿÿ‰T$‰$èQÃÿÿƒì‹EPEô‰D$‰$èY¿ÿÿEô‰$ènÂÿÿ‹E‰$èÓÿÿ‰Ã…@ÿÿÿ‰$èÃÃÿÿ‰Øë+‰ÃEô‰$èBÂÿÿë‰Ã…@ÿÿÿ‰$è Ãÿÿ‰Øë‰$èÃÿÿ‹]üÉÃU‰åSìÔÇD$…@ÿÿÿ‰$èÂÿÿ‹E ‰D$…@ÿÿÿ‰$èÚÀÿÿEô•@ÿÿÿ‰T$‰$è•Âÿÿƒì‹EPEô‰D$‰$è¾ÿÿEô‰$è²Áÿÿ‹E‰$è^Òÿÿ‰Ã…@ÿÿÿ‰$èÃÿÿ‰Øë+‰ÃEô‰$è†Áÿÿë‰Ã…@ÿÿÿ‰$èäÂÿÿ‰Øë‰$èXÂÿÿ‹]üÉÃU‰åƒì‹EƒÀ‰$èDäÿÿ‹E‹@ ;E } ‹E‹U ‰P ‹EƒÀ‰$è”ÔÿÿÉÃU‰åƒì‹E‹U ‰T$‰$è.‹E‰D$‹E ‰$èà¿ÿÿÉÃU‰åƒì‹E‰D$‹E ‰$è”×ÿÿÉÃU‰åƒì‹EƒÀ(‰D$‹E ‰$èËÿÿÿÉÃU‰åSƒìD‹E‰D$ ‹E‰D$‹E ‰D$EЉ$è ßÿÿ‹EUЉT$‰$èŸEЉ$è Öÿÿ‹E‹U‰T$‰$èb‹E‰$è#Ðÿÿë‰ÃEЉ$èàÕÿÿ‰Ø‰$è<ÁÿÿƒÄD[]ÃU‰åƒì‹E ‰D$‹E‰$è‹EÉÃU‰åƒì‹E ‰D$‹E‰$èGÉÃU‰å‹E‹U ‰P ‹E‹U ‰P$]ÃU‰å‹E]ÃU‰åƒì‹E ‰$èæÿÿÿ‹UƒÂ(‰D$‰$è…ÿÿÿÉÃU‰åƒì‹E ‰D$‹E‰$èÉÃU‰åƒìHÇD$(‹E‰D$EЉ$èN½ÿÿÇD$(‹E ‰D$‹E‰$è4½ÿÿÇD$(EЉD$‹E ‰$è½ÿÿÉÃU‰åSƒìD‹E ‰D$EЉ$è!ßÿÿ‹EUЉT$‰$è?ÿÿÿEЉ$è¬Ôÿÿ‹E‹U‰T$‰$èÿÿÿ‹E‰$èÃÎÿÿë‰ÃEЉ$è€Ôÿÿ‰Ø‰$èÜ¿ÿÿƒÄD[]ÃU‰åSƒì‹E P‹E‰T$‰$è ‹E‹U J‹UƒÂP‰D$‰L$‰$è‹¿ÿÿ‹E‹U J‹UƒÂX‰D$‰L$‰$èL¾ÿÿ‹E ‹‹E‰‹E ‹P‹E‰PP‹E‹ƒè‹‰Â‹E‹E ‹@‰‹E ‹P ‹E‰PXë?‰Ã‹E P‹EƒÀP‰T$‰$èå»ÿÿë‰Ã‹E P‹E‰T$‰$è‰Øë‰$è¿ÿÿƒÄ[]ÃU‰åSƒì‹E‰$èJÝÿÿ‹EƒÀ\‰$èZ»ÿÿº¤ò‹E‰T$‰$謋U¸¨ò‹MƒÁP‰T$‰D$‰ $蘾ÿÿ‹U¸°ò‹MƒÁX‰T$‰D$‰ $èZ½ÿÿºò‹E‰ºTò‹E‰PPº\‹E¸|ò‰ºhò‹E‰PXëM‰Ã¸¨ò‹UƒÂP‰D$‰$èþºÿÿë‰Ãº¤ò‹E‰T$‰$èë‰Ã‹EƒÀ\‰$è$¾ÿÿ‰Ø‰$è ¾ÿÿƒÄ[]ÃU‰åSƒì$‹E H‹E‹U‰T$‹U‰T$‹U‰T$ ‹U‰T$‰L$‰$踋E‹U J‹UƒÂP‰D$‰L$‰$è½ÿÿ‹E‹U J‹UƒÂX‰D$‰L$‰$è^¼ÿÿ‹E ‹‹E‰‹E ‹P‹E‰PP‹E‹ƒè‹‰Â‹E‹E ‹@‰‹E ‹P ‹E‰PXë?‰Ã‹E P‹EƒÀP‰T$‰$è÷¹ÿÿë‰Ã‹E P‹E‰T$‰$è‰Øë‰$è½ÿÿƒÄ$[]ÃU‰åSƒì$‹E‰$è\Ûÿÿ‹EƒÀ\‰$èl¹ÿÿº¤ò‹E‹M‰L$‹M‰L$‹M‰L$ ‹M ‰L$‰T$‰$訋U¸¨ò‹MƒÁP‰T$‰D$‰ $莼ÿÿ‹U¸°ò‹MƒÁX‰T$‰D$‰ $èP»ÿÿºò‹E‰ºTò‹E‰PPº\‹E¸|ò‰ºhò‹E‰PXëM‰Ã¸¨ò‹UƒÂP‰D$‰$èô¸ÿÿë‰Ãº¤ò‹E‰T$‰$èë‰Ã‹EƒÀ\‰$è¼ÿÿ‰Ø‰$è¼ÿÿƒÄ$[]ÃU‰åSƒì‹E H‹E‹U‰T$ ‹U‰T$‰L$‰$èè‹E‹U J‹UƒÂP‰D$‰L$‰$è¡»ÿÿ‹E‹U J‹UƒÂX‰D$‰L$‰$èbºÿÿ‹E ‹‹E‰‹E ‹P‹E‰PP‹E‹ƒè‹‰Â‹E‹E ‹@‰‹E ‹P ‹E‰PXë?‰Ã‹E P‹EƒÀP‰T$‰$èû·ÿÿë‰Ã‹E P‹E‰T$‰$è‰Øë‰$è»ÿÿƒÄ[]ÃU‰åSƒì‹E‰$è`Ùÿÿ‹EƒÀ\‰$èp·ÿÿº¤ò‹E‹M‰L$ ‹M ‰L$‰T$‰$èæ‹U¸¨ò‹MƒÁP‰T$‰D$‰ $è ºÿÿ‹U¸°ò‹MƒÁX‰T$‰D$‰ $èb¹ÿÿºò‹E‰ºTò‹E‰PPº\‹E¸|ò‰ºhò‹E‰PXëM‰Ã¸¨ò‹UƒÂP‰D$‰$è·ÿÿë‰Ãº¤ò‹E‰T$‰$è"ë‰Ã‹EƒÀ\‰$è,ºÿÿ‰Ø‰$èºÿÿƒÄ[]ÃU‰åƒì‹E ‹‹E‰‹EƒÀ(‰$èˆÎÿÿ‹E‰$裺ÿÿ¸…Àt ‹E‰$èo·ÿÿÉÃU‰åƒìº ø‹E‰‹EƒÀ(‰$èHÎÿÿ‹E‰$ècºÿÿ¸…Àt ‹E‰$è/·ÿÿÉÃU‰åƒì‹E‰$è¯ÿÿÿ‹E‰$è·ÿÿÉÃU‰åƒì‹E‹@$‹U ‰T$‰$è …À”À„Àt¸ë‹E‹U ‰P$¸ÉÃU‰å‹U‹E !Ð]ÃU‰åƒìÇD$‹E‰$èŸÿÿÿ„Àt‹EP(‹E ‰D$‰$è¶Òÿÿë¸ÿÿÿÿÉÃU‰åSƒìD‹E‹ƒÀ‹ÇD$Ç$è7ÇÿÿU؉D$ÇD$ÇD$ÿÿÿÿÇD$ ÿÿÿÿ‹E‰D$‰$ÿÓƒìE؉$èNÉÿÿ!Ѓøÿ”À„Àt ÇE ÿÿÿÿëq‹EƒÀ(‰$èÁÑÿÿ¶¾À;E •À„ÀtS‹E‹ƒÀ‹ÇD$Ç$è­ÆÿÿUè‰D$ÇD$ÇD$ÇD$ ‹E‰D$‰$ÿÓƒìÇE ÿÿÿÿ‹E ‹]üÉÃU‰åSƒì4‹E‰Eà‹E‰Eä‹E X(Mè‹E‰D$‹Eà‹Uä‰D$‰T$ ‰\$‰ $èÔÿÿƒìEè‰$èuÈÿÿ‰Eà‰Uä‹Eäƒðÿ‰Â‹Eàƒðÿ Ð…Àt ‹E ‹U‰P$‹Eà‹Uä‰D$‰T$‹E‰$èÈÿÿ‹E‹]üÉÂU‰åVSƒì ‹E ‹ƒÀ‹0E‰$èÈÿÿ‹M‹] ‰\$ÇD$‰D$‰T$ ‹E ‰D$‰ $ÿÖƒì‹Eeø[^]ÂU‰åƒì‹E‰$è9³ÿÿ‹E ‹‹E‰‹EÇ@ ‹E‹P ‹E‰P$‹EƒÀ(‰$èOÉÃU‰åƒì‹E‰$è)Õÿÿ‹E‰$èì²ÿÿº ø‹E‰‹EÇ@ ‹E‹P ‹E‰P$‹EƒÀ(‰$èÉÃU‰åƒì‹E‰$èÝÔÿÿºTô‹E‰‹EÇ@ÿÿÿÿ‹EÇ@‹EÇ@ ‹EÇ@‹EÇ@‹EÇ@‹EÇ@‹EÇ@ ‹EÇ@$ÉÃU‰åSƒì‹E‰$è2²ÿÿ‹E ‹‹E‰‹E‹U‰P ÇD$Ç$èMÄÿÿ‰D$‹E‰$è™üÿÿ‹U‰B$‹EP(‹E‰D$ ‹E‰D$‹E‰D$‰$èÓÿÿë‰Ã‹E‰$èT¶ÿÿ‰Ø‰$芵ÿÿƒÄ[]ÃU‰åSƒì‹E‰$èÔÓÿÿ‹E‰$è—±ÿÿº ø‹E‰‹E‹U‰P ÇD$Ç$è²Ãÿÿ‰D$‹E‰$èþûÿÿ‹U‰B$‹EP(‹E‰D$ ‹E‰D$‹E ‰D$‰$è‚Òÿÿë‰Ã‹E‰$è¹µÿÿ‰Ø‰$èï´ÿÿƒÄ[]ÃU‰åSƒì‹E‰$è±ÿÿ‹E ‹‹E‰‹E‹U‰P ÇD$Ç$è!Ãÿÿ‰D$‹E‰$èmûÿÿ‹U‰B$‹EP(‹E‰D$‰$èwÓÿÿÇD$ ‹E‰$è?ûÿÿ…Àu.ÇD$‹E‰$è(ûÿÿ…ÀtÇD$‹E‰$èûÿÿ…Àu¸ë¸„Àt9‹EƒÀ(‰$èÇÿÿë)‰Ã‹EƒÀ(‰$èªÈÿÿë‰Ã‹E‰$èÁ´ÿÿ‰Ø‰$è÷³ÿÿƒÄ[]ÃU‰åSƒì‹E‰$è@Òÿÿ‹E‰$è°ÿÿº ø‹E‰‹E‹U‰P ÇD$Ç$èÂÿÿ‰D$‹E‰$èjúÿÿ‹U‰B$‹EP(‹E ‰D$‰$ètÒÿÿÇD$ ‹E‰$è<úÿÿ…Àu.ÇD$‹E‰$è%úÿÿ…ÀtÇD$‹E‰$èúÿÿ…Àu¸ë¸„Àt9‹EƒÀ(‰$èÆÿÿë)‰Ã‹EƒÀ(‰$è§Çÿÿë‰Ã‹E‰$è¾³ÿÿ‰Ø‰$èô²ÿÿƒÄ[]ÃU‰åƒì‹EƒÀ(‰$èbÒÿÿÉÃU‰åƒìÇD$‹E‰$èQùÿÿ„Àt‹EƒÀ(‰$è«Çÿÿë¸ÿÿÿÿÉÃU‰åƒìÇD$‹E‰$èùÿÿ„Àt‹EP(‹E‰D$‹E ‰D$‰$èÑÌÿÿë¸ÿÿÿÿÉÃU‰åƒìÇD$‹E‰$èÛøÿÿ„Àt‹EP(‹E‰D$‹E ‰D$‰$è•Òÿÿë¸ÿÿÿÿÉÃUW1ÿVSè%³ÿÿÃí=ƒì‹l$0³äþÿÿè¡­ÿÿƒÜþÿÿ)ÆÁþ…öt'¶‹D$8‰,$‰D$‹D$4‰D$ÿ”»ÜþÿÿƒÇ9÷u߃Ä[^_]Ãë óÃSƒìè³²ÿÿÃ{=ƒÄ[à K kill (no lock) existing shared segment R remove existing shared segment S show stats of current shared segment L Load segment c create new shared memory (sets id) l lock segment id until key pressed p c put char c at offset x q quit r read n chars from offset x w args write all args at offset x ? Requested: id = No segment loaded Removing segment id = Loading segment cmd specification errorSegment id = at write offset at offset , to read bytes No data at Retrieved bytes, containing `' , to write No room left to write any bytes Wrote request not implemented: L£Þ£­­­­­L£‘¤­­­­­­­­­­­­­­­¢­­­­­­­­­­­­ì¤î¬Ŧ­­­­;ªÀ \Àóܰ¨±0œðœòç„èОíLííPœçŽíÊæ °ÿÿÿÀóž±ܱ¨ÿÿÿÀó”±Õ±¤ÿÿÿ¤ÿÿÿÀó‚±ƱòìòLó`óŒó óTò|òhò`ø$ædæ0œðœòç„èОíLííPœçŽíÊæ L.pŸ ôÿÿÿôÿÿÿL. 0€.0Ÿ€œüÿÿÿüÿÿÿ€.°žŸN3FBB12SharedStreamE¨.¨ó`øL.P€.XôôÿÿN3FBB12SharedEnum__EH-ðó’$I’$I"A°@<@@tôTôN3FBB12SharedMemoryE¨.\ôôôÿÿNo shared data avaiableID of shared memory segment: No shared memory data block attached Shared memory block attached at address , block index = SharedMutex::lock: failed to lock the segmentÀ Maximum possible offset = Current offset = , located in block Offset () exceeds maxOffset (À Can't attach shared segment segmentÀ Could not discard shared segment À Access mode: 0 Information readable until offset Size of the data segments: bytes data segments may be defined, with a total capacity of kB ID(s) of data segments: at idx : id = @Cannot create a shared segment segmentIncorrect size (, should be: ) of shared segmentÀ Failed to detach shared segmentÀ Can't determine segment size of segment : À `ø$ædæ0œðœòç„èОíLííPœçŽíÊæ ø¨.€øp/ôôÿÿN3FBB15SharedStreambufE;x®£ÿÿ”)©ÿÿ(Tµÿÿ“µÿÿô°µÿÿ¸¾µÿÿØ̵ÿÿøصÿÿîµÿÿ8¶ÿÿX¶ÿÿxd¶ÿÿ¸¬¶ÿÿຶÿÿ·ÿÿp·ÿÿØ·ÿÿ¸¸ÿÿظÿÿø8¸ÿÿ<Þ¸ÿÿ\ð¸ÿÿpú¸ÿÿ„¹ÿÿ˜"¹ÿÿ¸1¹ÿÿÌ8¹ÿÿà@¹ÿÿ” Ĺÿÿ عÿÿ4 ì¹ÿÿT ºÿÿt "ºÿÿ´ HºÿÿÔ rºÿÿô ¸ºÿÿ ¨»ÿÿ4 æ»ÿÿX $¼ÿÿ| J¼ÿÿà Ø¼ÿÿœ ä¼ÿÿ¼ ½ÿÿ@ '¾ÿÿ A¾ÿÿ \¾ÿÿl š¾ÿÿÌ Ð¾ÿÿŒ ä¾ÿÿ¬ ¿ÿÿ, \¿ÿÿì h¿ÿÿ ~¿ÿÿL ¿ÿÿ¬ xÀÿÿl „ÀÿÿŒ ¤Àÿÿ ìÀÿÿÌ Áÿÿì ÁÿÿP ¦Áÿÿ0 ²Áÿÿp BÂÿÿô 6Ãÿÿ BÃÿÿ° lÃÿÿÔ ‚Ãÿÿ Ãÿÿ8êÃÿÿ|ÆÄÿÿ ®Åÿÿ\´ÅÿÿÄ>ÆÿÿäÔÆÿÿÇÿÿ$TÇÿÿd¢ÇÿÿD¸Çÿÿ„lÈÿÿ¤>ÉÿÿÈRÉÿÿèÊÿÿÂÊÿÿ<úÊÿÿ\|Ëÿÿˆ¤Ëÿÿ¨ÆËÿÿÈÌÿÿ ¨Ìÿÿì¾Ìÿÿ,ÍÿÿLdÎÿÿ| Ïÿÿ¤ÞÏÿÿÌšÐÿÿô\Ñÿÿ/ÒÿÿHìÒÿÿ¤Óÿÿp²Óÿÿ°ØÓÿÿÐàÓÿÿðìÓÿÿÔÿÿp‘Ôÿÿ0™ÔÿÿPžÔÿÿ qÕÿÿÌ.Öÿÿô$Øÿÿô1Øÿÿ>Øÿÿ4HØÿÿTlØÿÿtØÿÿ”åØÿÿ´ ÙÿÿÔ2Ùÿÿ$€ÙÿÿD%ÛÿÿtáÛÿÿœÜÿÿÄ[ÝÿÿìÞÿÿÔÞÿÿ<ªßÿÿhfàÿÿКáÿÿ¸áÿÿ°ÌáÿÿÅâÿÿ0ãÿÿX=äÿÿ€úäÿÿ¨2åÿÿ^åÿÿÈxåÿÿè–åÿÿÈæÿÿ(4æÿÿHNæÿÿheæÿÿˆnæÿÿ¨“æÿÿð®æÿÿçÿÿ0vçÿÿXRèÿÿ€Héÿÿ¨@êÿÿÐRëÿÿü<ìÿÿ$@íÿÿL€íÿÿlÀíÿÿŒÞíÿÿÌîÿÿ¬&îÿÿìbîÿÿ Nïÿÿ0àïÿÿT2ðÿÿœtðÿÿ¼Àðÿÿ|8ñÿÿÜÈñÿÿdòÿÿ,\óÿÿT^ôÿÿ|tôÿÿœ¨ôÿÿ¼êôÿÿÜ,õÿÿüœõÿÿ8zR| ˆ €ÿÿF J tx?;*2$"@ð¯ÿÿA…B JÅ `Þ¯ÿÿ A…B IÅ €Ì¯ÿÿ A…B GÅ  ¸¯ÿÿA…B RÅ À®¯ÿÿA…B RÅ यÿÿA…B RÅ š¯ÿÿJA…B FÅ zPLR|`Ÿ ˆ$$¤¯ÿÿHôA…B DƒÃAÅ hįÿÿA…B JÅ $l²¯ÿÿYA…B DƒPÃAÅ D”ù¡ÿÿ+  D GuFupu|uxut Á AÃAÆAÇAÅC ø›¯ÿÿA…B DÅ $üƒ¯ÿÿ¼³A…B Gƒ±Åà @°ÿÿ6A…B rÅ `.°ÿÿ A…B IÅ  €°ÿÿA…B AƒUÃAÅ ¤0­ÿÿ?A…B {Å Äô¯ÿÿ¦A…B ¢Å äz°ÿÿøx°ÿÿ  n°ÿÿ  d°ÿÿA…B ZÅ @b°ÿÿT]°ÿÿhP°ÿÿ|—¬ÿÿA…B XÅ œ¨°ÿÿA…B OÅ ¼œ°ÿÿA…B OŠܰÿÿ*A…B fÅ üš°ÿÿ A…B GÅ ¤¯ÿÿƒA…B Å <f°ÿÿ&A…B bÅ \l°ÿÿ)A…B eÅ |v°ÿÿFA…B BÅ œœ°ÿÿïA…B ëÅ   l±ÿÿ>ËA…B zÅ  Ʊÿÿ>ÏA…B zÅ  ±ÿÿ&A…B bÅ $4²ÿÿ A…B GÅ  D ²ÿÿ%A…B Dƒ\ÃAÅ hb±ÿÿA…B ‰Å ˆ³ÿÿA…B VÅ ¨³ÿÿA…B VÅ (ȱÿÿA…B E†ƒÃAÆAÅ ôè²ÿÿ=A…B yÅ <³ÿÿA…B OÅ 40³ÿÿ*A…B fÅ TƲÿÿ6A…B rÅ th³ÿÿ A…B GÅ ”T³ÿÿA…B RÅ ´Ú²ÿÿNA…B JÅ Ô*³ÿÿDA…B @Å ô´ÿÿ A…B GÅ ð³ÿÿA…B [Å 4³ÿÿ¶A…B ²Å T´ÿÿA…B RÅ t´ÿÿ A…B GÅ  ”³ÿÿGA…B Dƒ~ÃAÅ ¸n´ÿÿ A…B GŠض³ÿÿ˜A…B ”Å ø:´ÿÿA…B ŒÅ žµÿÿ A…B GÅ  8еÿÿ)A…B Dƒ`ÃAÅ \µÿÿA…B QÅ  |F´ÿÿôA…B DƒëÃAÅ  bµÿÿA…B ZÅ  À`µÿÿJA…B Dƒ@Åà äJ·ÿÿA…B AÅ  èfµÿÿÜÓA…B ØÅ  ¶ÿÿçâA…B ãÅ L è¶ÿÿŠA…B †Å l R·ÿÿ•A…B ‘Å Œ È·ÿÿ/A…B kÅ ¬ Ø·ÿÿPA…B LÅ Ì V¸ÿÿA…B RÅ ì è·ÿÿNA…B JÅ  ,¸ÿÿ³A…B ¯Å  , À¸ÿÿÑA…B DƒÈÃAÅ P n¹ÿÿA…B OÅ (T b¹ÿÿ³ñA…B E†ƒ¨ÃAÆAÅ $€ é¹ÿÿ¼A…B Gƒ±Åà Ä ~ºÿÿ8A…B tÅ (ä –ºÿÿA…B F‡†ƒtÃAÆAÇAÅ  ìºÿÿ(A…B dÅ 0 ôºÿÿ"A…B ^Å  P öºÿÿBA…B DƒyÃAÅ t ´»ÿÿA…B QÅ ” ôºÿÿŸA…B ™Å ´ Š»ÿÿQA…B MÅ ,¸ ¼»ÿÿTA…B E†ƒIÃAÆAÅ $è à¼ÿÿ¼7A…B Gƒ±Åà $ t½ÿÿ¾OA…B Gƒ³Åà $8 ¾ÿÿ¼gA…B Gƒ±Åà $` ž¾ÿÿÂA…B Gƒ·Åà (ˆ 8¿ÿÿÓ—A…B E†ƒÈÃAÆAÅ $´ ß¿ÿÿ¼ªA…B Gƒ±Åà ø ,ÁÿÿA…B JÅ  TÀÿÿ·A…B ³Å 8 úÀÿÿ&A…B `Å X ÁÿÿA…B DÅ x èÀÿÿ A…B GÅ ˜ ÔÀÿÿA…B VÅ ¸ YÁÿÿA…B DÅ Ø AÁÿÿA…B AÅ ,Ü ŽÀÿÿ‹ÚA…B F‡†ƒ~ÃAÆAÇAÅ ( öÀÿÿÓêA…B E†ƒÈÃAÆAÅ $8 Áÿÿ¼A…B Gƒ±Åà |(Äÿÿ A…B IÅ œÄÿÿ A…B IÅ ¼Äÿÿ A…B FÅ ÜìÃÿÿ$A…B `Å üðÃÿÿ$A…B `Å ôÃÿÿUA…B QÅ <)Äÿÿ&A…B bÅ \/Äÿÿ&A…B bÅ ,|2ÁÿÿöA…B F‡†ƒéÃAÆAÇAÅ ¬ÄÿÿNA…B JÅ ,°4Äÿÿ¥3A…B E†ƒšÃAÆAÅ $à©Åÿÿ¼^A…B Gƒ±Åà $=Æÿÿ¼vA…B Gƒ±Åà $0ÑÆÿÿ¾ŽA…B Gƒ³Åà $XgÇÿÿ¼¦A…B Gƒ±Åà $€ûÇÿÿ¼¾A…B Gƒ±Åà (¨ÈÿÿÖÖA…B E†ƒËÃAÆAÅ $Ô:Éÿÿ¼éA…B Gƒ±Åà ËÿÿA…B YÅ 8ËÿÿA…B OÅ 0<ŽÉÿÿ3A…B F‡†ƒ&ÃAÆAÇAÅ (pÀÊÿÿùA…B E†ƒîÃAÆAÅ $œËÿÿ¼2A…B Gƒ±Åà $Ä!Ìÿÿ¼bA…B Gƒ±Åà $ìµÌÿÿ¼zA…B Gƒ±Åà 0JÍÿÿ8A…B tÅ PŽÍÿÿA…B VÅ pˆÍÿÿA…B YÅ "Íÿÿ,A…B hÅ °æÍÿÿA…B YÅ ÐäÍÿÿA…B VÅ ðÞÍÿÿA…B SÅ ÕÍÿÿA…B DÅ 0¾Íÿÿ%A…B aÅ $4ÆÌÿÿ€’A…B DƒwÃAÅ x›ÍÿÿA…B VÅ ˜–ÍÿÿVA…B RÅ $œÌÍÿÿr¢A…B DƒiÃAÅ $ÄÎÿÿܲA…B DƒÓÃAÅ $ìÊÎÿÿöÊA…B DƒíÃAÅ $˜ÏÿÿøæA…B DƒïÃAÅ (<hÐÿÿþA…B Dƒ ÃAÅ $hNÑÿÿêA…B DƒáÃAÅ $Òÿÿ3A…B DƒûÃAÅ ÔìÒÿÿ?A…B {Å ô Óÿÿ?A…B {Å ,ÓÿÿA…B ZÅ 4eÓÿÿ A…B IÅ T Óÿÿ;A…B wÅ t2Óÿÿ;A…B wÅ  ”NÓÿÿìA…B DƒäÅà  ¸Ôÿÿ‘A…B Dƒ‡Åà $Ü„ÔÿÿRA…B E†ƒEÃAÆAÅ <ÕÿÿwA…B sÅ $ŽÔÿÿAA…B }Å D°ÔÿÿLA…B HÅ $HTÕÿÿOA…B Dƒ‡ÃAÅ $p¼Õÿÿ›`A…B Dƒ’ÃAÅ $˜0Öÿÿ÷qA…B DƒîÃAÅ $À×ÿÿ‰A…B DƒùÃAÅ Ú×ÿÿA…B RÅ $Ð×ÿÿ4A…B pÅ Dä×ÿÿBA…B ~Å dØÿÿBA…B ~Å 8„(ØÿÿaA…A ‡C†AƒN0HAÃAÆ AÇAÅÀ\Øÿÿÿÿ$+=ÿÿ5<Nÿÿ¢ —>¹ƒ¦¼ûîƒÉ›äƒ“ Aî ƒš CÀƒ ®– ŸÅ ÀÇ ¼ë À i¾£±Àˆ²'íÿ×’ÈÁíåäÝíì%éÔ!ƒšÿÿ¯0›]Œ²ÿÿÿÿÿÿ ‡IÒÕÿÿ ’IÝàÿÿB˜U‰„(ÿÿ¯0›]Œ²ÿÿ¥·¸K¦¡ÅÈÿÿ¯0›]Œ²ÿÿ±2_Ž´ÿÿ¯0›]Œ²ÿÿµ6¡c’¸ÿÿN¸a ©Ÿ-ÿÿ¯0›]Œ²ÿÿ±2_Ž´ÿÿ ak~ÿÿQ¶d §¢ÄÇÿÿ¯0›]Œ²ÿÿ±2_Ž´ÿÿ'Më`Ü–ÒˆåOùÒ–™ÿÿ¯0›]Œ²ÿÿ¯0›]Œ²ÿÿ±2_Ž´ÿÿ¯0›]Œ²ÿÿ¯0›]Œ²ÿÿdºw«¦(ÿÿ¯0›]Œ²ÿÿ#M·¤Ú¦ÿÿRÜe@ÍÃêíÿÿ¯0›]Œ²ÿÿ±2_Ž´ÿÿ¯0›]Œ²ÿÿ¯0›]Œ²ÿÿ "4c\ÿÿ &UNÿÿÎ6³U—Ñÿÿ/ÖM¾k£ëÿÿ3êRÏq³íÿÿKòiÚ‡¿‡ÿÿ%ÜDÁc¥ßÿÿ=ä[Ìy±ùÿÿ ls…ÿÿ w~ÿÿ ^ÚÁÈìÿÿiåÌÓ÷ ¡7®€¡ßS g „ ”› Dî¤*¬*õþÿoŒ°Š@ƒ ; È+€™¼˜XþÿÿoÜ—ÿÿÿoðÿÿoì–´*Ö›æ›ö›œœ&œ6œFœVœfœvœ†œ–œ¦œ¶œÆœÖœæœöœ&6FVfv†–¦¶ÆÖæöžž&ž6žFžVžfžvž†ž–ž¦ž¶žÆžÖžæžöžŸŸ&Ÿ6ŸFŸVŸfŸvŸ†Ÿ–Ÿ¦Ÿ¶ŸÆŸÖŸæŸöŸ  & 6 F V f v † – ¦ ¶ Æ GCC: (Debian 4.8.2-1) 4.8.2GCC: (Debian 4.7.3-7) 4.7.3.symtab.strtab.shstrtab.interp.note.ABI-tag.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rel.dyn.rel.plt.init.text.fini.rodata.eh_frame_hdr.eh_frame.gcc_except_table.init_array.fini_array.jcr.dynamic.got.got.plt.data.bss.comment44#HH 1hh$DöÿÿoŒŒ´N @ƒ@pV°Š° ; ^ÿÿÿoì–ìîkþÿÿoÜ—Üàz ¼˜¼Xƒ ™€ Œ”›”#‡À›À’РÐ rM˜DîDnž`î`nD ¦¤ø¤x|´ þ ~Ô¾ôô•­Ð¤*¤šÜ¬*¬šè°*°ší´*´šöÄ+Ä›ûÈ+È›L-  -\ 08TD£à¼ $´,4HhŒ@ƒ°Šì–Ü—¼˜ ™ ”› À› Р Dî`î¤ø þô¤*¬*°*´*Ä+È+- -ñÿ °*¡ .@¡ A€¡ Wx/f¬* ¡ ™¤*¸ñÿÇhîây/ñø­? !7® 5ðñfñÿÇôxñÿÇôñÿÇôñÿÇô£ñÿÇ@ô±ñÿÇŒô¸ñÿÇôÂñÿÇ*õÊñÿÇ+õÒñÿÇ,õÝñÿÇ-õåñÿÇ.õíñÿÇ/õôñÿÇ0õûñÿÇ1õñÿÇ2õñÿÇ3õñÿÇ4õ#ñÿÇ5õ4ñÿÇ6õEñÿÇ7õRñÿÇ8õ\ñÿÇ9õiñÿÇ:õrñÿÇ;õ£ñÿÇ<õÊñÿÇ@õ5tõ€ñÿÇxõ¸ñÿÇyõñÿǼõ¢ñÿǽõ¶ñÿǾõñÿÇ¿õEñÿÇÀõ¿ñÿÇÄõ5äõÉñÿÇèõ5öxñÿÇöÓñÿÇöÝñÿÇö5@ö¸ñÿÇHöîñÿÇ÷ùñÿÇ÷5|÷ñÿÇ€÷5¤÷ñÿǨ÷&ñÿǬ÷5Ü÷.ñÿÇà÷AñÿÇá÷LñÿÇâ÷UñÿÇã÷^ñÿÇä÷oñÿÇå÷€ñÿÇæ÷£ñÿÇç÷‘ñÿǘø™ñÿÇ™ø¥ñÿÇšø²ñÿÇ›ø½ñÿÇœøÈñÿÇøÜñÿÇžøðñÿÇŸøEñÿÇ øñÿÇ¡øñÿÇ¢øñÿÇ£øñÿ%ð3°*ñÿ?´*H¬*Y¤*lÈ+‚H¹G ž·¨ó!Ðê@ó(!t·" $j½ç ZÒÎö }fÃ8 –ì ÄiÛ¼" ìð›Óʼ" *ÖèA GöÁ³ c>Ú" |Ʋ&" ¥Ʊ" Ljµ%" àpÚù þ"¸D \ô!3¿¯¼" [ºÞ" x‰|®" ¨Ð-׎íB üLÅ" ÿÕ¼" C¦¹ " e¢Ñ$" ½Ç¼" ädæ  ´ÅT  …Ô¼" D çì i ^¯Y" ƒ 0œÎ ¯H" ä B Pœƒ déw" „Ì " Ç - Ò lê›  Þ" B j dîy ¨ßr § FÀ" Ñ D¼J þ ž± "  T €œk ‚æ; › ·= ¸ æ»)" Ñ |°6" ï HÌ" æºô 0 ²¹˜ L òÞ" „ » P¯" Ò fÃ8 ë `îò R¾" äâ SÍ¡+  X}(¹" ˜àä Ãå¶" áø»Ö¼" žÃ >²*" ^HÄ" tx¿/ –¨¿\Ú" ØbÅQ ÷T®" ¯H" !-.ìÐ$" Ií n -!ƒÎ¼" Åðœ %ܼ" 0`ø !Láܼ" w‰ä±ƒ ±Éº² " çâÐ " ÿ ¸ " 8Xô!Q0pòç‘ ´5Í" ¼Ö Ä( 슴> À°" )@-,![„èR ¤ÅÚ» " ìDîò>·6 ¯Ñ&" $ܱ" D|°6" b޼Ü ˜¨±" ²Ëì²) é¡ ÿÌ" -ÉÓ¼" UpÞ" ’‚ȼ" º€ó(!Ø ò$!ñ Ù3 h²" ,$æ? I·¯" ŠAÕ¾" ®T®" ÂÙ˶" üJº " R¾" 2FÜé VÌ&" ÉÚ÷²·N 7Êæ; [Р bjÄB ¦ë½æ " ß%" <¬ÄŸ eƒâÁ œºí4 ß>ÉÂ" \Ú"  ¸" D”› J¹" l¹ " ‡—f¸¶ ³-¿€- !Ô^¯Y" îNؼ" Hø!2Pðó!i¬¨¿P ËæÖÑN  3LíB W‡\À³ ¨’®" Ê-!è‰Ñ&" ýäå? ø¿N <Õ±" \ŒÈÐ " ¦öãê ÑÀ-Œè¾®J" ¼" (Vº Gp® " c…L´> Ÿ>Ú" ¸àòD!1È´&" \ò„!uŒìáø Ótô!ì-ùÖÝ,  ˆ·*" = |/B °ža ܰ¦" { âÁ ” ô!­ ØÞ" Í  !L.! !О`!-l!²° " Œ!±!Àó0!Ê!ÁÑ ñ!žÝ8 "7"Ðía G"Ë· f"}"Ÿœ"|²" º"\³ï # Ù3 #€ø!<#RßV" u#Ë#0Ÿâ#4ÑU" $@Ÿ#$BÍÓ K$]$àÜ w$`Ÿ˜$x×Ö ½$ªÌ‹ á$ÄǾ" %:Þ€ O%‚±" q%pŸˆ%éL ¥%î%&€.!&1&L&•&§&æ& .,!' 8'Hô !Q'i'$Ò¥ 'ÕÐ " ©'X¾Š Ã'P¯" Ú'(@î (ÊÓ @(b® " Z( y(—(à.­(©Â¼" Õ(|µ " ù()ë÷ H)¨®" h)Ì" –)p/!Ð)7ß" ú)&¼ *öàö 3* B* ß" ‡*ž*=Í" §*®µ É* ã*⾕ ý*øD!+|Ì" E+b+¨+³F É+Ù+î´ õ+,”± " 2,  W,”,À "crtstuff.c__JCR_LIST__deregister_tm_clonesregister_tm_clones__do_global_dtors_auxcompleted.6008__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entrylocaldriver.cc_ZStL19piecewise_construct_ZStL8__ioinit_Z41__static_initialization_and_destruction_0ii_GLOBAL__sub_I_main_ZZL18__gthread_active_pvE20__gthread_active_ptrblockavailable.ccclear.ccclearall.cccomputesegmentsize.ccdestructor.ccget.ccinsert.cckill.cclock.cclockall.ccmap1.ccmap2.ccptr.ccput.ccread.ccreadblock.ccremove1.ccseek.ccsharedmemory2.ccsharedmemory3.ccshowmanyc.ccunlock.ccunlockall.ccwrite.ccwriteblock.ccsharedmutex1.ccoperatorplusis.ccoperatorplusplus.ccreset.ccupdate.ccattach.cccreate.ccdeletesegment.ccnewdata.ccnewsegment.ccrawdetach.ccsharedsegment1.ccsize.ccupdatenreadable.ccmeminfo.ccopen1.ccopen2.ccsharedstream1.ccsharedstream2.ccsharedstream3.ccmode.ccoverflow.ccpbackfail.ccseekoff.ccseekpos.ccsharedstreambuf1.ccsharedstreambuf2.ccsharedstreambuf3.ccunderflow.ccxsgetn.ccxsputn.cc__FRAME_END____JCR_END___DYNAMIC__init_array_end__init_array_start_GLOBAL_OFFSET_TABLE__ZN3FBB12SharedMemory3ptrEv_ZNSo3putEc@@GLIBCXX_3.4_ZTSN3FBB12SharedStreamE_ZNSspLERKSs@@GLIBCXX_3.4_ZTCN3FBB12SharedStreamE80_Si_ZN3FBB11SharedBlock4lockEv_ZN3FBB12SharedMemoryC1EjNS_12SharedEnum__8SizeUnitEj_ZNK3FBB13SharedSegment6insertERSo_ZN3FBB11SharedMutexC2Ev_ZN3FBB15SharedStreambufC1EiSt13_Ios_Openmode_ZN3FBBlsIA41_cEEONS_9ExceptionES3_RKT__ZN3FBB9ExceptionD1Ev_ZN3FBBlsIA36_cEEONS_9ExceptionES3_RKT__ZN3FBB15SharedStreambufC2Ev_ZN3FBB11SharedMutex4lockEv_ZN3FBB11SharedBlockC2Ev_ZN3FBB13SharedSegment6detachIcEEPT_S3_b_ZTv0_n12_N3FBB12SharedStreamD0Ev_ZNK3FBB9SharedPos3eofEv_ZN3FBB13SharedSegment4sizeEi_ZN3FBB12SharedMemory3mapEv_ZTSN3FBB12SharedMemoryE_ZN3FBBlsIA24_cEEONS_9ExceptionES3_RKT__ZN3FBB12SharedMemoryaSEOS0_shmdt@@GLIBC_2.0_ZNK3FBB15SharedStreambuf2idEvpthread_mutexattr_setpshared@@GLIBC_2.2_edata_ZN3FBB15SharedStreambuf6xsputnEPKci_ZNK3FBB9SharedPos9nReadableEv_ZN3FBBlsIA14_cEEONS_9ExceptionES3_RKT__ZNK3FBB9SharedPos11blockOffsetEv_ZNSt15basic_streambufIcSt11char_traitsIcEEC2Ev@@GLIBCXX_3.4_ZStaNRSt13_Ios_FmtflagsS__ZN3FBBlsIA9_cEEONS_9ExceptionES3_RKT__ZN3FBB15SharedStreambufD0Ev_ZN3FBB9SharedPos6updateEv_ZN3FBBlsIA17_cEEONS_9ExceptionES3_RKT__ZN3FBB15SharedStreambuf9pbackfailEi_ZN3FBB9ExceptionC2ERKS0__ZNSt15basic_streambufIcSt11char_traitsIcEE5imbueERKSt6locale@@GLIBCXX_3.4_ZN3FBB9ExceptionC1Ev_ZSt7getlineIcSt11char_traitsIcESaIcEERSt13basic_istreamIT_T0_ES7_RSbIS4_S5_T1_E@@GLIBCXX_3.4_ZNSt15basic_streambufIcSt11char_traitsIcEE5uflowEv@@GLIBCXX_3.4_ZN3FBB12SharedMemoryC1Ev_ZNK3FBB6RangerIPNS_11SharedBlockEE3endEvdata_start_ZN3FBB15SharedStreambufC1EjNS_12SharedEnum__8SizeUnitESt13_Ios_Openmodej_ZNK3FBB15SharedStreambuf7memInfoERSo_ZNSolsEPFRSt8ios_baseS0_E@@GLIBCXX_3.4_IO_stdin_used_ZN3FBB12SharedStream4openEiSt13_Ios_Openmode_ZN3FBB13SharedSegment15nReadableUnlockEv_ZN3FBB12SharedMemory4seekExSt12_Ios_Seekdir_ZThn80_N3FBB12SharedStreamD1Ev_ZNSt9basic_iosIcSt11char_traitsIcEEC2Ev@@GLIBCXX_3.4_ZNSoD0Ev@@GLIBCXX_3.4_ZN3FBB15SharedStreambuf4modeESt13_Ios_Openmode_ZN3FBB12SharedMemory4killEv_ZNK3FBB9SharedPos3eosEv_ZNSt4fposI11__mbstate_tEC2Ex_ZN3FBB11SharedBlock5setIDEi_ZN3FBB12SharedMemory9readBlockEPcj_ZN3FBB12SharedMemory3putEi_ZN3FBB15SharedStreambuf11setOpenModeESt13_Ios_Openmode_ZNKSt9basic_iosIcSt11char_traitsIcEEntEv@@GLIBCXX_3.4_ZNSt9exceptionC1ERKS__ZN3FBB11SharedMutexC1Ev_fp_hw_ZN3FBB12SharedEnum__C2Ev_ZN3FBB12SharedStreamC1EjNS_12SharedEnum__8SizeUnitESt13_Ios_Openmodejmain__cxa_allocate_exception@@CXXABI_1.3_ZN3FBB13SharedSegmentixEj_ZN3FBB12SharedStreamC1EiSt13_Ios_Openmode_ZN3FBBlsERSoRKNS_9SharedPosE_ZNSiD2Ev@@GLIBCXX_3.4_ZN3FBBlsIA20_cEEONS_9ExceptionES3_RKT__ZNK3FBB9SharedPos6insertERSo_ZN3FBB13SharedSegment6unlockEj_ZN3FBB9SharedPosppEv_ZN3FBB12SharedMemory9showmanycEvmemcpy@@GLIBC_2.0_ZNSolsEx@@GLIBCXX_3.4_ZN3FBB11SharedBlockD2Ev_ZNK3FBB9SharedPos9showmanycEv_ZNSt9exceptionC2Ev_ZN3FBB9ExceptionC2Ev__dso_handle_ZStoRRSt13_Ios_FmtflagsS__ZN3FBB15SharedStreambuf9showmanycEv_ZTVN3FBB9ExceptionE_ZNSsC1ERKSs@@GLIBCXX_3.4_ZN3FBBlsIA34_cEEONS_9ExceptionES3_RKT__ZNSt15basic_streambufIcSt11char_traitsIcEE6setbufEPci@@GLIBCXX_3.4_ZN3FBBlsIA3_cEEONS_9ExceptionES3_RKT__ZTIN3FBB15SharedStreambufE_ZN3FBBlsIFRSoS1_EEEONS_9ExceptionES4_RKT_shmctl@@GLIBC_2.2_ZN3FBB12SharedMemory14blockAvailableEj_ZNSirsERi@@GLIBCXX_3.4_ZNK3FBB9SharedPos8blockIdxEv_ZStcoSt13_Ios_Fmtflags_ZNSiD0Ev@@GLIBCXX_3.4_ZNK3FBB13SharedSegment7nBlocksEv_ZTTN3FBB12SharedMemoryE_ZTv0_n12_NSiD0Ev@@GLIBCXX_3.4_ZN3FBB15SharedStreambuf7seekoffExSt12_Ios_SeekdirSt13_Ios_Openmode_ZnwjPv__cxa_atexit@@GLIBC_2.1.3_ZN3FBB9SharedPospLEj_ZN3FBB12SharedMemoryD1Ev_ZNKSt4fposI11__mbstate_tEmiERKS1__ZTVN10__cxxabiv117__class_type_infoE@@CXXABI_1.3_ZN3FBB15SharedStreambuf7seekposESt4fposI11__mbstate_tESt13_Ios_Openmode__cxa_free_exception@@CXXABI_1.3_ZNK3FBB13SharedSegment11segmentSizeEv_fini_ZN3FBB12SharedMemory4lockEj_ZSt3octRSt8ios_base_ZThn80_N3FBB12SharedStreamD0Ev_ZNSt4fposI11__mbstate_tEC1Ex_ZN3FBB12SharedMemoryC2EjNS_12SharedEnum__8SizeUnitEj_ZN3FBB12SharedStreamD0Ev_ZNSolsEPKv@@GLIBCXX_3.4_ZN3FBB12SharedMemory5clearEv__x86.get_pc_thunk.bx_ZN3FBB6RangerIPNS_11SharedBlockEEC2ERKS2_S5__ZN3FBBlsIA39_cEEONS_9ExceptionES3_RKT__ZNSo5tellpEv@@GLIBCXX_3.4_ZN3FBBlsERSoRKNS_12SharedMemoryE_ZN3FBBlsIA22_cEEONS_9ExceptionES3_RKT__ZTCN3FBB12SharedStreamE88_So_ZTTN3FBB12SharedStreamE_ZN3FBB13SharedSegmentC1Ejjj_ZN3FBB11SharedMutex6unlockEv_ZN3FBB15SharedStreambufD1Ev_ZSt4moveIRN3FBB9ExceptionEEONSt16remove_referenceIT_E4typeEOS4__ZN3FBBlsIjEEONS_9ExceptionES2_RKT__ZNSt9exceptionC1Ev_ZNSsC1Ev@@GLIBCXX_3.4_ZN3FBBlsERSoRKNS_13SharedSegmentE_ZNK3FBB9SharedPos6offsetEv_ZN3FBB12SharedEnum__C1Ev_ZdlPv@@GLIBCXX_3.4_ZN3FBB15SharedStreambufC2EjNS_12SharedEnum__8SizeUnitESt13_Ios_Openmodej_ZN3FBB6rangerINS_11SharedBlockEEENS_6RangerIPT_EES4_S4_shmat@@GLIBC_2.0__libc_start_main@@GLIBC_2.0_ZN3FBB12SharedMemory7lockAllEvpthread_mutex_unlock@@GLIBC_2.0_ZN3FBB15SharedStreambuf8overflowEi_start_ZN3FBB9SharedPos5resetEPNS_13SharedSegmentE_ZNSoD2Ev@@GLIBCXX_3.4_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@@GLIBCXX_3.4_ZStanSt13_Ios_OpenmodeS__ZN3FBB15SharedStreambuf9setMemoryEONS_12SharedMemoryE_ZN3FBB9SharedPos4seekExSt12_Ios_Seekdir_ZNSolsEPFRSoS_E@@GLIBCXX_3.4_ZN3FBB11SharedMutexD1Evpthread_mutex_init@@GLIBC_2.0_ZN3FBB15SharedStreambuf9underflowEv_ZN3FBBlsIcEEONS_9ExceptionES2_RKT__ZN3FBB11SharedBlockD1Ev_ZN3FBB13SharedSegment13nReadableLockEv_init_ZNK3FBB9SharedPos11atMaxOffsetEv_ZNK3FBB11SharedBlock2idEvsqrt@@GLIBC_2.0_ZN3FBB12SharedMemory3mapEj__TMC_END___ZTIN3FBB9ExceptionE_ZN3FBB9ExceptionC1ERKS0__ZN3FBBlsIA32_cEEONS_9ExceptionES3_RKT__ZTTN3FBB15SharedStreambufEpthread_mutex_lock@@GLIBC_2.0_ZTSN3FBB12SharedEnum__E_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c@@GLIBCXX_3.4_ZN3FBB12SharedMemory6unlockEj_ZNKSs4dataEv@@GLIBCXX_3.4_ZN3FBB13SharedSegment7newDataEj_Jv_RegisterClasses_ZNSirsERx@@GLIBCXX_3.4_ZN3FBB15SharedStreambuf6xsgetnEPci_ZNSo5seekpESt4fposI11__mbstate_tE@@GLIBCXX_3.4_ZN3FBB12SharedMemory5writeEPKci_ZN3FBB15SharedStreambuf6removeEv_ZTVSt9exception@@GLIBCXX_3.4_ZSt3decRSt8ios_base_ZN3FBB15SharedStreambufD2Ev_ZN3FBB12SharedMemory9unlockAllEv_ZThn88_N3FBB12SharedStreamD0Ev_ZNSi5seekgESt4fposI11__mbstate_tE@@GLIBCXX_3.4_ZStanSt13_Ios_FmtflagsS__ZN3FBB12SharedStreamC2EiSt13_Ios_Openmode_ZSt4cout@@GLIBCXX_3.4_ZN3FBB12SharedStream5clearEv_ZNK3FBB9SharedPos11segmentSizeEv_ZN3FBB12SharedMemory4readEPci_ZNK3FBB12SharedMemory2idEvpthread_mutexattr_init@@GLIBC_2.0_ZN3FBB12SharedMemoryD2Ev_ZN3FBB11SharedBlockC1Ev_ZStrsIcSt11char_traitsIcEERSt13basic_istreamIT_T0_ES6_RS3_@@GLIBCXX_3.4_ZTCN3FBB12SharedStreamE0_NS_15SharedStreambufE_ZN3FBB13SharedSegment6detachIS0_EEPT_S3_b_ZTVN3FBB12SharedStreamE_ZNSolsEj@@GLIBCXX_3.4_ZN3FBB12SharedStreamC2EjNS_12SharedEnum__8SizeUnitESt13_Ios_Openmodej_ZTIN3FBB12SharedMemoryE__data_start_ZNK3FBB12SharedStream7memInfoERSoPKc_ZN3FBB13SharedSegment4lockEj_end_ZTv0_n12_NSoD1Ev@@GLIBCXX_3.4_ZN3FBB12SharedStreamD1Ev_ZN3FBB11SharedMutexD2Ev_ZTIN3FBB12SharedEnum__E_ZN3FBB12SharedMemory4swapERS0__ZNSoC2EPSt15basic_streambufIcSt11char_traitsIcEE@@GLIBCXX_3.4_ZTISi@@GLIBCXX_3.4_ZNSt15basic_streambufIcSt11char_traitsIcEE4syncEv@@GLIBCXX_3.4__bss_start_ZNKSt4fposI11__mbstate_tEcvxEv_ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4_ZTIN3FBB12SharedStreamE_ZN3FBB12SharedMemory10writeBlockEPKcj_ZN3FBB13SharedSegment15updateNreadableEi_ZNSi4readEPci@@GLIBCXX_3.4__libc_csu_init_ZN3FBB13SharedSegment5clearEv_ZNSsD1Ev@@GLIBCXX_3.4_ZTv0_n12_NSoD0Ev@@GLIBCXX_3.4_ZN3FBB11SharedBlock6unlockEv_ZN3FBB12SharedMemory18computeSegmentSizeEPjxNS_12SharedEnum__8SizeUnitE_ZN3FBB13SharedSegmentC2Ejjj_ZTSN3FBB15SharedStreambufE_ZN3FBB5FSwap3XchINS_12SharedMemoryELj40EE5fswapERS2_S4__ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEEC1ESt13_Ios_Openmode@@GLIBCXX_3.4_ZNSoD1Ev@@GLIBCXX_3.4_ZNSt8ios_base4setfESt13_Ios_FmtflagsS0__ZN3FBB10errnodescrERSo_ZN3FBB13SharedSegment13deleteSegmentEimemset@@GLIBC_2.0_ZN3FBB12SharedStreamC2Ev__gxx_personality_v0@@CXXABI_1.3_ZN3FBB13SharedSegment9rawDetachEPvb_ZN3FBB13SharedSegment6createEPijjj_ZN3FBBlsIiEEONS_9ExceptionES2_RKT__ZN3FBB12SharedStream4openEjNS_12SharedEnum__8SizeUnitESt13_Ios_Openmodej_ZTv0_n12_N3FBB12SharedStreamD1Ev_ZNSiD1Ev@@GLIBCXX_3.4_ZN3FBB15SharedStreambufC1Ev_ZNSt9basic_iosIcSt11char_traitsIcEE5clearESt12_Ios_Iostate@@GLIBCXX_3.4__cxa_throw@@CXXABI_1.3_ZTISo@@GLIBCXX_3.4_ZNSolsEi@@GLIBCXX_3.4_ZNSi5tellgEv@@GLIBCXX_3.4_ZNKSt19basic_ostringstreamIcSt11char_traitsIcESaIcEE3strEv@@GLIBCXX_3.4shmget@@GLIBC_2.0_ZNSiC2EPSt15basic_streambufIcSt11char_traitsIcEE@@GLIBCXX_3.4_ZTVN10__cxxabiv121__vmi_class_type_infoE@@CXXABI_1.3_ITM_deregisterTMCloneTable_ZTVN3FBB12SharedMemoryE_Unwind_Resume@@GCC_3.0_ZN3FBB13SharedSegment10newSegmentEjj_ZStorSt13_Ios_FmtflagsS__ZN3FBB12SharedMemoryC2Ei_ZNSt9exceptionC2ERKS__ZNSt9basic_iosIcSt11char_traitsIcEED2Ev@@GLIBCXX_3.4__libc_csu_fini_ZN3FBB13SharedSegment6attachEi_ZStorSt13_Ios_OpenmodeS__ZTv0_n12_NSiD1Ev@@GLIBCXX_3.4_ZNSo5writeEPKci@@GLIBCXX_3.4_ZSt3cin@@GLIBCXX_3.4_ZN3FBBlsIA46_cEEONS_9ExceptionES3_RKT__ZNK3FBB13SharedSegment9nReadableEv_ZNSt9exceptionD2Ev@@GLIBCXX_3.4_ZN3FBB15SharedStreambufC2EiSt13_Ios_Openmode_ZN3FBB15SharedStreambuf4killEv_ZN3FBB6RangerIPNS_11SharedBlockEEC1ERKS2_S5__ZTISt15basic_streambufIcSt11char_traitsIcEE@@GLIBCXX_3.4_ZN3FBB5fswapINS_12SharedMemoryEEEvRT_S3__ZN3FBB12SharedMemory6removeEv_ZN3FBB12SharedStreamC1Ev__gmon_start___ZSt4moveIRN3FBB12SharedMemoryEEONSt16remove_referenceIT_E4typeEOS4__ZNSolsEd@@GLIBCXX_3.4_ZdlPvS__ZNK3FBB12SharedMemory6insertERSo_ITM_registerTMCloneTable_ZN3FBB12SharedMemoryC1Ei_ZTVN3FBB15SharedStreambufE_ZNK3FBB6RangerIPNS_11SharedBlockEE5beginEv_ZNKSs6lengthEv@@GLIBCXX_3.4_ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev@@GLIBCXX_3.4_ZN3FBB12SharedMemory8clearAllEvceil@@GLIBC_2.0_ZN3FBB12SharedMemory3getEv_ZNKSi6gcountEv@@GLIBCXX_3.4_ZThn88_N3FBB12SharedStreamD1Ev_ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4_ZNSt15basic_streambufIcSt11char_traitsIcEED2Ev@@GLIBCXX_3.4__pthread_key_create@@GLIBC_2.0bobcat-3.19.01/sharedstream/driver/driver.cc0000644000175000017500000001224612242405663017673 0ustar frankfrank#include #include #include #include #include #include using namespace std; using namespace FBB; int main() { SharedStream shared; int id = -1; while (true) { cout << "\n" " K kill (no lock) existing shared segment\n" " R remove existing shared segment\n" " S show stats of current shared segment\n" " L Load segment \n" " c create new shared memory (sets id)\n" " l lock segment id until key pressed\n" " p c put char c at offset x\n" " q quit\n" " r read n chars from offset x\n" " w args write all args at offset x\n" "? "; char ch; cin >> ch; ios::off_type offset; cout << "Requested: " << ch << '\n'; shared.clear(); switch (ch) { case 'c': { shared.open(1, SharedStream::kB); id = shared.id(); cout << "id = " << id << '\n'; shared.memInfo(cout); cout << '\n'; } break; case 'K': // delete segment case 'R': // delete segment { if (id == -1) { cout << "No segment loaded\n"; continue; } cout << "Removing segment id = " << id << '\n'; if (ch == 'R') shared.remove(); else shared.kill(); id = -1; } break; case 'L': cin >> id; cout << "Loading segment " << id << '\n'; shared.open(id); shared.memInfo(cout); cout << '\n'; break; case 'S': if (id == -1) { cout << "No segment loaded\n"; continue; } shared.memInfo(cout); cout << '\n'; break; case 'p': // put a char behind the last written { if (id == -1) { cout << "No segment loaded\n"; continue; } cin >> offset >> ch; if (!cin) throw Exception() << "cmd specification error"; shared.seekp(offset); cout << "Segment id = " << id << " at write offset " << shared.tellp() << '\n'; shared.put(ch); } break; case 'r': // put a char behind the last written { if (id == -1) { cout << "No segment loaded\n"; continue; } int n; cin >> offset >> n; if (!cin) throw Exception() << "cmd specification error"; char buf[n]; shared.seekg(offset); cout << "Segment id = " << id << " at offset " << shared.tellg() << ", to read " << n << " bytes\n"; n = shared.read(buf, n).gcount(); if (n < 0) cout << "No data at " << offset << '\n'; else { cout << "Retrieved " << n << " bytes, containing `"; cout.write(buf, n); cout << "'\n"; for (auto ch: buf) cout << static_cast(ch) << ' '; cout << '\n'; } } break; case 'w': // write chars at offset { if (id == -1) { cout << "No segment loaded\n"; continue; } string line; cin >> offset; getline(cin, line); if (!cin) throw Exception() << "cmd specification error"; streampos pos = shared.seekp(offset).tellp(); cout << "Segment id = " << id << " at offset " << pos << ", to write " << line.length() << " bytes\n"; shared.write(line.data(), line.length()); if (!shared) cout << "No room left to write any bytes\n"; else cout << "Wrote " << (shared.tellp() - pos) << " bytes\n"; } break; case 'q': return 0; default: cout << "request not implemented: " << ch << '\n'; break; } } } bobcat-3.19.01/sharedstream/sharedstream3.cc0000644000175000017500000000026312240137210017632 0ustar frankfrank#include "sharedstream.ih" SharedStream::SharedStream(int id, std::ios::openmode openMode) : SharedStreambuf(id, openMode), std::istream(this), std::ostream(this) {} bobcat-3.19.01/sharedstream/sharedstream.ih0000644000175000017500000000010312237775134017576 0ustar frankfrank#include "sharedstream" using namespace std; using namespace FBB; bobcat-3.19.01/sharedstream/sharedstream1.cc0000644000175000017500000000014512240140010017617 0ustar frankfrank#include "sharedstream.ih" SharedStream::SharedStream() : istream(this), ostream(this) {} bobcat-3.19.01/sharedstreambuf/0000755000175000017500000000000012257325714015272 5ustar frankfrankbobcat-3.19.01/sharedstreambuf/remove.f0000644000175000017500000000010112242144403016712 0ustar frankfrankinline void SharedStreambuf::remove() { d_memory.remove(); } bobcat-3.19.01/sharedstreambuf/kill.f0000644000175000017500000000007512242144456016372 0ustar frankfrankinline void SharedStreambuf::kill() { d_memory.kill(); } bobcat-3.19.01/sharedstreambuf/sharedstreambuf2.cc0000644000175000017500000000047112242117642021035 0ustar frankfrank#include "sharedstreambuf.ih" SharedStreambuf::SharedStreambuf( size_t maxSize, SharedMemory::SizeUnit sizeUnit, std::ios::openmode openMode, size_t access) : d_openMode(openMode), d_currentMode(openMode & (ios::in | ios::out)), d_memory(maxSize, sizeUnit, access) {} bobcat-3.19.01/sharedstreambuf/destructor.cc0000644000175000017500000000010612240660720017763 0ustar frankfrank#include "sharedstreambuf.ih" SharedStreambuf::~SharedStreambuf() {} bobcat-3.19.01/sharedstreambuf/sharedstreambuf.ih0000644000175000017500000000010612242144626020763 0ustar frankfrank#include "sharedstreambuf" using namespace std; using namespace FBB; bobcat-3.19.01/sharedstreambuf/underflow.cc0000644000175000017500000000016512241200064017567 0ustar frankfrank#include "sharedstreambuf.ih" int SharedStreambuf::underflow() { return mode(ios::in) ? d_memory.get() : EOF; } bobcat-3.19.01/sharedstreambuf/id.f0000644000175000017500000000010512242144334016020 0ustar frankfrankinline int SharedStreambuf::id() const { return d_memory.id(); } bobcat-3.19.01/sharedstreambuf/xsputn.cc0000644000175000017500000000025512241233171017130 0ustar frankfrank#include "sharedstreambuf.ih" std::streamsize SharedStreambuf::xsputn(char const *buf, std::streamsize len) { return mode(ios::out) ? d_memory.write(buf, len) : EOF; } bobcat-3.19.01/sharedstreambuf/mode.cc0000644000175000017500000000027012241233203016504 0ustar frankfrank#include "sharedstreambuf.ih" bool SharedStreambuf::mode(ios::openmode flag) { if (not (d_currentMode & flag)) return false; d_currentMode = flag; return true; } bobcat-3.19.01/sharedstreambuf/meminfo.f0000644000175000017500000000012712242144576017072 0ustar frankfrankinline void SharedStreambuf::memInfo(std::ostream &out) const { out << d_memory; } bobcat-3.19.01/sharedstreambuf/clear.f0000644000175000017500000000010012242144527016511 0ustar frankfrankinline void SharedStreambuf::clear() { d_memory.clear(); } bobcat-3.19.01/sharedstreambuf/sharedstreambuf0000644000175000017500000000507112244427062020372 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SHAREDSTREAMBUF_ #define INCLUDED_BOBCAT_SHAREDSTREAMBUF_ #include #include #include namespace FBB { class SharedStreambuf: public std::streambuf, public virtual SharedEnum__ { std::ios::openmode d_openMode; std::ios::openmode d_currentMode; // initially openMode, thereafter // either ::in or ::out SharedMemory d_memory; public: SharedStreambuf(); // 1 SharedStreambuf( size_t maxSize, SizeUnit sizeUnit, // 2 std::ios::openmode openMode = std::ios::in | std::ios::out, size_t access = 0600); SharedStreambuf( // 3 int id, std::ios::openmode openMode = std::ios::in | std::ios::out); virtual ~SharedStreambuf(); int id() const; // id of the shared Memory segment void kill(); // kill all shared segments w/o locks // the object is unusable hereafter void remove(); // remove all shared segments. // the object is unusable hereafter void clear(); // clear all existing data and reduce // until only the segment at // d_sharedData void setMemory(SharedMemory &&tmp); void memInfo(std::ostream &out) const; protected: void setOpenMode(std::ios::openmode openMode); private: bool mode(std::ios::openmode flag); int pbackfail(int ch) override; std::streamsize showmanyc() override; int underflow() override; std::streamsize xsgetn(char *buf, std::streamsize n) override; int overflow(int c) override; std::streamsize xsputn(char const *buf, std::streamsize n) override; std::ios::pos_type seekoff( std::ios::off_type offset, std::ios::seekdir way = std::ios::beg, std::ios::openmode mode = std::ios::in | std::ios::out) override; std::ios::pos_type seekpos( std::ios::pos_type offset, std::ios::openmode mode = std::ios::in | std::ios::out) override; }; #include "setopenmode.f" #include "id.f" #include "remove.f" #include "kill.f" #include "clear.f" #include "setmemory.f" #include "meminfo.f" } // FBB #endif bobcat-3.19.01/sharedstreambuf/seekpos.cc0000644000175000017500000000031012236242272017236 0ustar frankfrank#include "sharedstreambuf.ih" ios::pos_type SharedStreambuf::seekpos(ios::pos_type offset, ios::openmode mode) { return seekoff(offset, ios::beg, mode); } bobcat-3.19.01/sharedstreambuf/setmemory.f0000644000175000017500000000013612242144540017453 0ustar frankfrankinline void SharedStreambuf::setMemory(SharedMemory &&tmp) { d_memory = std::move(tmp); } bobcat-3.19.01/sharedstreambuf/setopenmode.f0000644000175000017500000000020312242144277017753 0ustar frankfrankinline void SharedStreambuf::setOpenMode(std::ios::openmode openMode) { d_openMode = openMode; d_currentMode = openMode; } bobcat-3.19.01/sharedstreambuf/overflow.cc0000644000175000017500000000022512241665061017436 0ustar frankfrank#include "sharedstreambuf.ih" int SharedStreambuf::overflow(int ch) { //cerr << "overflow\n"; return mode(ios::out) ? d_memory.put(ch) : EOF; } bobcat-3.19.01/sharedstreambuf/seekoff.cc0000644000175000017500000000043212236411234017210 0ustar frankfrank#include "sharedstreambuf.ih" ios::pos_type SharedStreambuf::seekoff( ios::off_type offset, ios::seekdir way, ios::openmode mode) { offset = d_memory.seek(offset, way); if (offset != -1) d_currentMode = mode; return offset; } bobcat-3.19.01/sharedstreambuf/sharedstreambuf1.cc0000644000175000017500000000022412240135552021026 0ustar frankfrank#include "sharedstreambuf.ih" SharedStreambuf::SharedStreambuf() : d_openMode(static_cast(0)), d_currentMode(d_openMode) {} bobcat-3.19.01/sharedstreambuf/sharedstreambuf3.cc0000644000175000017500000000053712242116645021043 0ustar frankfrank#include "sharedstreambuf.ih" SharedStreambuf::SharedStreambuf(int id, std::ios::openmode openMode) : d_openMode(openMode), d_currentMode(openMode & (ios::in | ios::out)), d_memory(id) { if ( openMode & ios::trunc || (openMode & ios::out and not (openMode & ios::in)) ) d_memory.clear(); } bobcat-3.19.01/sharedstreambuf/showmanyc.cc0000644000175000017500000000015412236411264017602 0ustar frankfrank#include "sharedstreambuf.ih" streamsize SharedStreambuf::showmanyc() { return d_memory.showmanyc(); } bobcat-3.19.01/sharedstreambuf/xsgetn.cc0000644000175000017500000000023512236411551017101 0ustar frankfrank#include "sharedstreambuf.ih" streamsize SharedStreambuf::xsgetn(char *data, streamsize len) { return mode(ios::in) ? d_memory.read(data, len) : EOF; } bobcat-3.19.01/sharedstreambuf/pbackfail.cc0000644000175000017500000000036012236502600017500 0ustar frankfrank#include "sharedstreambuf.ih" int SharedStreambuf::pbackfail(int ch) { if (seekoff(-1) == -1) ch = EOF; else if (*d_memory.ptr() != ch) { seekoff(+1); // undo the seek ch = EOF; } return ch; } bobcat-3.19.01/signal/0000755000175000017500000000000012257522663013372 5ustar frankfrankbobcat-3.19.01/signal/signal0000644000175000017500000000214712257021556014571 0ustar frankfrank#ifndef INCLUDED_SIGNAL_ #define INCLUDED_SIGNAL_ #include #include namespace FBB { class SignalHandler { friend class Signal; public: virtual ~SignalHandler(); private: virtual void signalHandler(size_t signum) = 0; }; class Signal { typedef std::vector SignalHandlerVector; std::vector d_signals; // d_signals is a vector of vectors of pointers to SignalHandlers // the row dimension refers to the signal number // each row holds a SignalHandler object handling that kind of signal static Signal *s_signal; public: static Signal &instance(); Signal(Signal const &) = delete; Signal &operator=(Signal const &) = delete; void add(size_t signum, SignalHandler &object); void remove(size_t signum, SignalHandler &object); void ignore(size_t signum); void reset(size_t signum); private: Signal(); static void verify(size_t signum, char const *member); static void handler(int signum); }; } #endif bobcat-3.19.01/signal/destructor.cc0000644000175000017500000000007112222576524016072 0ustar frankfrank#include "signal.ih" SignalHandler::~SignalHandler() {} bobcat-3.19.01/signal/instance.cc0000644000175000017500000000023512222576524015502 0ustar frankfrank#include "signal.ih" Signal *Signal::s_signal; Signal &Signal::instance() { if (s_signal == 0) s_signal = new Signal; return *s_signal; } bobcat-3.19.01/signal/handler.cc0000644000175000017500000000022012222576524015305 0ustar frankfrank#include "signal.ih" void Signal::handler(int signum) { for (auto &obj: s_signal->d_signals[signum]) obj->signalHandler(signum); } bobcat-3.19.01/signal/driver/0000755000175000017500000000000012222576524014662 5ustar frankfrankbobcat-3.19.01/signal/driver/build0000755000175000017500000000011312222576524015702 0ustar frankfrank#!/bin/bash g++ --std=c++0x -Wall -O2 -odriver driver.cc ../*.cc -lbobcat bobcat-3.19.01/signal/driver/driver.cc0000644000175000017500000000224112222576524016463 0ustar frankfrank#include #include #include #include "../signal" class SignalDemo: public FBB::SignalHandler { volatile size_t d_signal; volatile bool d_continue; pid_t d_pid; public: SignalDemo(); void run(); private: virtual void signalHandler(size_t signum) override; }; using namespace std; using namespace FBB; SignalDemo::SignalDemo() : d_signal(0), d_continue(true), d_pid(getpid()) {} void SignalDemo::run() { while (d_continue) { cout << "Send a SIGHUP or SIGTERM... to process " << d_pid << endl; sleep(1); } cout << "Ending `run' after receiving signal " << d_signal << endl; } void SignalDemo::signalHandler(size_t signal) { if (signal == SIGHUP) cout << "Process " << d_pid << " received SIGHUP" << endl; else if (signal == SIGTERM) { cout << "Process " << d_pid << " received SIGTERM" << endl; d_signal = SIGTERM; d_continue = false; } } int main() { SignalDemo signalDemo; Signal::instance().add(SIGHUP, signalDemo); Signal::instance().add(SIGTERM, signalDemo); signalDemo.run(); } bobcat-3.19.01/signal/signal1.cc0000644000175000017500000000005212222576524015231 0ustar frankfrank#include "signal.ih" Signal::Signal() {} bobcat-3.19.01/signal/add.cc0000644000175000017500000000041112257020312014405 0ustar frankfrank#include "signal.ih" void Signal::add(size_t signum, SignalHandler &object) { verify(signum, "Signal::add"); if (d_signals.size() <= signum) d_signals.resize(signum + 1); d_signals[signum].push_back(&object); signal(signum, handler); } bobcat-3.19.01/signal/verify.cc0000644000175000017500000000041212222576524015177 0ustar frankfrank#include "signal.ih" void Signal::verify(size_t signum, char const *member) { if (signum > static_cast(SIGRTMAX)) throw Exception(1) << member << " signal " << signum << " exceeds " "max. signum (" << SIGRTMAX << ')'; } bobcat-3.19.01/signal/reset.cc0000644000175000017500000000023712222576524015022 0ustar frankfrank#include "signal.ih" void Signal::reset(size_t signum) { verify(signum, "Signal::reset"); signal(signum, SIG_DFL); d_signals[signum].clear(); } bobcat-3.19.01/signal/signal.ih0000644000175000017500000000021712257021526015161 0ustar frankfrank#include "signal" //#include // TMP #include #include using namespace std; using namespace FBB; bobcat-3.19.01/signal/ignore.cc0000644000175000017500000000024112222576524015156 0ustar frankfrank#include "signal.ih" void Signal::ignore(size_t signum) { verify(signum, "Signal::ignore"); signal(signum, SIG_IGN); d_signals[signum].clear(); } bobcat-3.19.01/signal/remove.cc0000644000175000017500000000114312257021526015165 0ustar frankfrank#include "signal.ih" void Signal::remove(size_t signum, SignalHandler &object) { verify(signum, "Signal::remove"); if (d_signals.size() <= signum) throw Exception(1) << "no signal handlers for signal " << signum << " were installed"; auto iter = find(d_signals[signum].begin(), d_signals[signum].end(), &object); if (iter == d_signals[signum].end()) throw Exception(1) << "object " << &object << " did not register a handler for signal " << signum; d_signals[signum].erase(iter); signal(signum, handler); } bobcat-3.19.01/socketbase/0000755000175000017500000000000012257325714014236 5ustar frankfrankbobcat-3.19.01/socketbase/reuse.f0000644000175000017500000000011712223757427015532 0ustar frankfrankinline bool SocketBase::reuse() const { return boolOption(SO_REUSEADDR); } bobcat-3.19.01/socketbase/setdebug.f0000644000175000017500000000014212223757536016210 0ustar frankfrankinline bool SocketBase::setDebug(bool trueIsOn) { return setBoolOption(SO_DEBUG, trueIsOn); } bobcat-3.19.01/socketbase/socketbase1.f0000644000175000017500000000017012223757631016607 0ustar frankfrankinline SocketBase::SocketBase(int socket, sockaddr_in const &address) : InetAddress(address), d_sock(socket) {} bobcat-3.19.01/socketbase/socket.f0000644000175000017500000000007512223757510015673 0ustar frankfrankinline int SocketBase::socket() const { return d_sock; } bobcat-3.19.01/socketbase/socketbase2.cc0000644000175000017500000000056412222576536016761 0ustar frankfrank#include "socketbase.ih" SocketBase::SocketBase(string const &host, uint16_t port) : InetAddress(host, port) { d_sock = ::socket(AF_INET, SOCK_STREAM, 0); // 0: protocol, should be 0 if (d_sock < 0) throw Exception() << "SocketBase::SocketBase(" << host << ", " << port << "): " << errnodescr; } bobcat-3.19.01/socketbase/debug.f0000644000175000017500000000011312223757404015464 0ustar frankfrankinline bool SocketBase::debug() const { return boolOption(SO_DEBUG); } bobcat-3.19.01/socketbase/socketbase.ih0000644000175000017500000000016712222576536016711 0ustar frankfrank#include "socketbase" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/socketbase/verify.cc0000644000175000017500000000007512222576536016055 0ustar frankfrank#include "socketbase.ih" void SocketBase::verify() const {} bobcat-3.19.01/socketbase/socketbase0000644000175000017500000000232112223760026016272 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SOCKETBASE_ #define INCLUDED_BOBCAT_SOCKETBASE_ #include #include #include // int info coming in/going out: host byte order namespace FBB { class SocketBase: public InetAddress { int d_sock; public: ~SocketBase() = default; void verify() const; bool debug() const; // .f bool reuse() const; // .f int socket() const; // .f bool setDebug(bool trueIsOn); // .f bool setReuse(bool trueIsOn); // .f protected: explicit SocketBase(uint16_t port); // 1 SocketBase(std::string const &host, uint16_t port); // 2 SocketBase(int socket, sockaddr_in const &address); // 1.f private: bool boolOption(int optname) const; bool setBoolOption(int optname, bool newValue); }; #include "socketbase1.f" #include "debug.f" #include "reuse.f" #include "setdebug.f" #include "setreuse.f" #include "socket.f" } // FBB #endif bobcat-3.19.01/socketbase/socketbase1.cc0000644000175000017500000000041512222576536016753 0ustar frankfrank#include "socketbase.ih" SocketBase::SocketBase(uint16_t port) : InetAddress(port) { d_sock = ::socket(AF_INET, SOCK_STREAM, 0); // 0: protocol, should be 0 if (d_sock < 0) throw Exception() << "SocketBase::SocketBase(port): " << errnodescr; } bobcat-3.19.01/socketbase/setbooloption.cc0000644000175000017500000000045712222576536017455 0ustar frankfrank#include "socketbase.ih" bool SocketBase::setBoolOption(int optname, bool newValue) { bool oldValue = boolOption(optname); if (setsockopt(d_sock, SOL_SOCKET, optname, &newValue, sizeof(bool)) < 0) throw Exception() << "SocketBase::getOption(): " << errnodescr; return oldValue; } bobcat-3.19.01/socketbase/booloption.cc0000644000175000017500000000046712222576536016742 0ustar frankfrank#include "socketbase.ih" bool SocketBase::boolOption(int optname) const { int value; socklen_t valueSize = sizeof(int); if (getsockopt(d_sock, SOL_SOCKET, optname, &value, &valueSize) < 0) throw Exception() << "SocketBase::getOption(): " << errnodescr; return value != 0; } bobcat-3.19.01/socketbase/setreuse.f0000644000175000017500000000014612223757577016256 0ustar frankfrankinline bool SocketBase::setReuse(bool trueIsOn) { return setBoolOption(SO_REUSEADDR, trueIsOn); } bobcat-3.19.01/stat/0000755000175000017500000000000012257325714013066 5ustar frankfrankbobcat-3.19.01/stat/access.cc0000644000175000017500000000204012222600571014617 0ustar frankfrank#include "stat.ih" bool Stat::access(User const &user, size_t spec, bool useEffective) const { bool userIsOwner = (spec & (UR | UW | UX)) && ( user.userid() == uid() or (useEffective && user.eUserid() == uid()) ); bool userInGroup = (spec & (GR | GW | GX)) && user.inGroup(gid(), useEffective); size_t mod = mode(); return ( // Read test: (mod & OR) || ((mod & UR) && userIsOwner) || ((mod & GR) && userInGroup) || not (spec & READ) ) and ( // Write test: (mod & OW) || ((mod & UW) && userIsOwner) || ((mod & GW) && userInGroup) || not (spec & WRITE) ) and ( // Exec test: (mod & OX) || ((mod & UX) && userIsOwner) || ((mod & GX) && userInGroup) || not (spec & EXEC) ); } bobcat-3.19.01/stat/gid.f0000644000175000017500000000010612223777103013771 0ustar frankfrankinline size_t Stat::gid() const { return d_stat.st_gid; } bobcat-3.19.01/stat/blocksize.f0000644000175000017500000000012012223776602015212 0ustar frankfrankinline size_t Stat::blockSize() const { return d_stat.st_blksize; } bobcat-3.19.01/stat/stat1.cc0000644000175000017500000000006112222600571014413 0ustar frankfrank#include "stat.ih" Stat::Stat() { init(); } bobcat-3.19.01/stat/specialmode.cc0000644000175000017500000000061512222600571015651 0ustar frankfrank#include "stat.ih" bool Stat::specialMode(size_t mode, Combine combi) const { if (mode & ~(SUID | SGID | SB)) throw Exception(1) << '0' << oct << mode << ": unknown special mode specification"; return (combi == ALL && mode == (d_stat.st_mode & (SUID | SGID | SB))) || (combi == ANY && (mode & d_stat.st_mode)); } bobcat-3.19.01/stat/lastmodification.f0000644000175000017500000000015012223777353016565 0ustar frankfrankinline DateTime Stat::lastModification() const { return DateTime(d_stat.st_mtime, DateTime::UTC); } bobcat-3.19.01/stat/size.f0000644000175000017500000000010712223777573014214 0ustar frankfrankinline off_t Stat::size() const { return d_stat.st_size; } bobcat-3.19.01/stat/type.f0000644000175000017500000000014012223777717014220 0ustar frankfrankinline Stat::Type Stat::type() const { return static_cast(d_stat.st_mode & S_IFMT); } bobcat-3.19.01/stat/istype.f0000644000175000017500000000010512223777061014545 0ustar frankfrankinline bool Stat::isType(Type probe) { return type() == probe; } bobcat-3.19.01/stat/nlinks.f0000644000175000017500000000011312223777530014526 0ustar frankfrankinline size_t Stat::nLinks() const { return d_stat.st_nlink; } bobcat-3.19.01/stat/mode.cc0000644000175000017500000000057012222600571014310 0ustar frankfrank#include "stat.ih" bool Stat::mode(size_t mode, Combine combi) const { if (mode & ~(UR | UW | UX | RWX)) throw Exception(1) << '0' << oct << mode << ": unknown mode specification"; return (combi == ALL && mode == (d_stat.st_mode & RWX)) || (combi == ANY && (mode & d_stat.st_mode)); } bobcat-3.19.01/stat/mode.f0000644000175000017500000000010612223777371014161 0ustar frankfrankinline size_t Stat::mode() const { return d_stat.st_mode & RWX; } bobcat-3.19.01/stat/stat2.cc0000644000175000017500000000012612222600571014416 0ustar frankfrank#include "stat.ih" Stat::Stat(string const &name) : d_name(name) { init(); } bobcat-3.19.01/stat/set.cc0000644000175000017500000000015712222600571014160 0ustar frankfrank#include "stat.ih" bool Stat::set(string const &name) { d_name = name; init(); return !d_errno; } bobcat-3.19.01/stat/opbool.f0000644000175000017500000000010012223776546014524 0ustar frankfrankinline Stat::operator bool() const { return d_errno == 0; } bobcat-3.19.01/stat/inode.f0000644000175000017500000000011012223777122014320 0ustar frankfrankinline size_t Stat::inode() const { return d_stat.st_ino; } bobcat-3.19.01/stat/statstruct.f0000644000175000017500000000011112223777620015446 0ustar frankfrankinline Stat::stat const &Stat::statStruct() const { return d_stat; } bobcat-3.19.01/stat/stat1.f0000644000175000017500000000014512223776433014272 0ustar frankfrankinline Stat::Stat(std::string const &name, std::string const &pathlist) { set(name, pathlist); } bobcat-3.19.01/stat/uid.f0000644000175000017500000000010412223777737014022 0ustar frankfrankinline size_t Stat::uid() const { return d_stat.st_uid; } bobcat-3.19.01/stat/nblocks.f0000644000175000017500000000011512223777504014666 0ustar frankfrankinline size_t Stat::nBlocks() const { return d_stat.st_blocks; } bobcat-3.19.01/stat/lastaccess.f0000644000175000017500000000014212223777176015365 0ustar frankfrankinline DateTime Stat::lastAccess() const { return DateTime(d_stat.st_atime, DateTime::UTC); } bobcat-3.19.01/stat/error.f0000644000175000017500000000010212223777007014356 0ustar frankfrankinline size_t Stat::error() const { return d_errno; } bobcat-3.19.01/stat/driver/0000755000175000017500000000000012222576540014356 5ustar frankfrankbobcat-3.19.01/stat/driver/build0000755000175000017500000003740512222576540015414 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/driver // script generated by the C++ icmake script version 2.20 /* Configurable defines: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BISON_FLAGS: This directive is only used when a grammar is generated using bison++. It defines the set of flags that are given to bison++ when bison++ generates the parser. By default the following flags are specified: -v -l The -d and -o flags are always provided (not configurable) BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (by default it is defined to the name of the program to be created). COMPILER: The compiler to use. COPT: C-options used by COMPILER LOPT: Define this (default: to "`wx-config --lib`") if a wxWindows program is constructed. In that case, you probably also want to define the COPT option `wx-config --cxxflags`, using, e.g., the following definition: #define COPT "-Wall `wx-config --cxxflags`" ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) GRAMMAR_LINES: When this directive is defined, #line directives will be generated at the first C++ compound statement in each individual grammar specification file. Undefine if no such #line directives are required. LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking QT: Define this (default: to "qt") if the unthreaded QT library is used. Define as "qt-mt" if the threaded QT library is used. If set, header files are grepped for the occurrence of the string '^[[:space:]]*Q_OBJECT[[:space:]]*$'. If found, moc -o moc.cc .h is called if the moc-file doesn't exist or is older than the .h file. Also, if defined the proper QT library is linked, assuming that the library is found in the ld-search path (E.g., see the environment variable $LIBRARY_PATH). Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY #define BUILD_PROGRAM "driver" #define COMPILER "g++" #define COPT "-Wall" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "" // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path ofiles, // wildcards for o-files sources, // sources to be used current, // contains name of current dir. programname; // the name of the program to create int nClasses, // number of classes/subdirectories program; // 1: program is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); #ifdef GRAMMAR_LINES system("./grambuild lines"); #else system("./grambuild"); #endif chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { #ifdef BISON_FLAGS exec("bison++", BISON_FLAGS, "-d", "-o", "parser.cc", "grammar"); #else exec("bison++", "-d", "-o", "parser.cc", "grammar"); #endif } chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || ( exists("../parser/parser.h") && "../parser/parser.h" younger "yylex.cc" ) ) ) exec("flex", interactive, "lexer"); chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; programname = BUILD_PROGRAM; #else program = 0; #endif; cwd = chdir("."); #ifdef GRAMBUILD if (exists("parser")) // subdir parser exists { CLASSES += "parser "; parser(); } if (exists("scanner")) // subdir scanner exists { CLASSES += "scanner "; scanner(); } #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* M O C . I M */ void moc(string class) { string hfile; string mocfile; int ret; hfile = class + ".h"; mocfile = "moc" + class + ".cc"; if ( hfile younger mocfile // no mocfile or younger h file && // and Q_OBJECT found in .h file !system(P_NOCHECK, "grep '^[[:space:]]*Q_OBJECT[;[:space:]]*$' " + hfile) ) // then call moc. system("moc -o " + mocfile + " " + hfile); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY files = altered(files, library); // keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library) { printf("\n"); exec(COMPILER, "-o", programname, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef QT "-l" + QT, #endif "-L.", libpath, lopt #ifdef LOPT , LOPT #endif #ifndef GDB , "-s" #endif ); printf("ok: ", programname, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library) { int index; string class; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { class = element(index, classes); // next class to process chdir(class); // change to directory current = "subdir " + class; #ifdef QT moc(class); // see if we should call moc #endif std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir #endif if (mainfile != "") // mainfile -> do link { link(library); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "driver.cc", // program source "driver" // static program library ); #else cpp_make ( "", "driver" // static- or so-library ); #endif } bobcat-3.19.01/stat/driver/driver.cc0000644000175000017500000000174412222576540016166 0ustar frankfrank/* driver.cc */ #include #include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { if (argc == 1) { cout << "Usage: driver object [colon-separated searchpath]\n"; return 1; } Stat st; if (argc == 2) st.set(argv[1]); else if (argc == 3) st.set(argv[1], argv[2]); if (!st) { cout << "Can't stat " << argv[1] << ", errno = " << st.error() << endl; return 1; } cout << st.name() << ": access: " << st.lastAccess() << "\n" << st.name() << ": change: " << st.lastChange() << "\n" << st.name() << ": modif: " << st.lastModification() << "\n" "Mode: " << oct << st.mode() << " (" << st.modeStr() << ")\n" "Type: " << st.type() << " (" << st.typeStr() << ")\n" "Full path: " << st.path() << endl; return 0; } bobcat-3.19.01/stat/devicetype.f0000644000175000017500000000011612223776761015401 0ustar frankfrankinline size_t Stat::deviceType() const { return d_stat.st_rdev; } bobcat-3.19.01/stat/set2.cc0000644000175000017500000000066712222600571014250 0ustar frankfrank#include "stat.ih" bool Stat::set(string const &name, string const &pathlist) { if (name[0] == '/') return set(name); vector element; String::split(&element, pathlist, ":"); for ( vector::iterator it = element.begin(); it != element.end(); ++it ) { if (set(*it + "/" + name)) return true; } return false; } bobcat-3.19.01/stat/path.cc0000644000175000017500000000023312222600571014314 0ustar frankfrank#include "stat.ih" string Stat::path() { auto_ptr buf(new char[PATH_MAX]); return !realpath(d_name.c_str(), buf.get()) ? "" : buf.get(); } bobcat-3.19.01/stat/stat3.cc0000644000175000017500000000020212222600571014412 0ustar frankfrank#include "stat.ih" Stat::Stat(Stat &&tmp) : d_stat(tmp.d_stat), d_errno(tmp.d_errno), d_name( move(tmp.d_name) ) {} bobcat-3.19.01/stat/typestr.cc0000644000175000017500000000127712222600571015103 0ustar frankfrank#include "stat.ih" string Stat::typeStr() const { string ret; switch (type()) { case BLOCK_DEVICE: ret = "BLOCK_DEVICE"; break; case CHARACTER_DEVICE: ret = "CHARACTER_DEVICE"; break; case DIRECTORY: ret = "DIRECTORY"; break; case FIFO: ret = "FIFO"; break; case REGULAR_FILE: ret = "REGULAR_FILE"; break; case SOCKET: ret = "SOCKET"; break; case SYMBOLIC_LINK: ret = "SYMBOLIC_LINK"; break; default: // ANY intentionally not handled break; } return ret; } bobcat-3.19.01/stat/modestr.cc0000644000175000017500000000077012222600571015043 0ustar frankfrank#include "stat.ih" string Stat::modeStr() const { string ret = "rwxrwxrwx"; size_t mode = d_stat.st_mode; for (size_t idx = 9; idx--; mode >>= 1) { if ((mode & 1) == 0) // bit not set ret[idx] = '-'; } if (d_stat.st_mode & SUID) ret[2] = ret[2] == 'x' ? 's' : 'S'; if (d_stat.st_mode & SGID) ret[5] = ret[5] == 'x' ? 's' : 'S'; if (d_stat.st_mode & SB) ret[8] = ret[8] == 'x' ? 't' : 'T'; return ret; } bobcat-3.19.01/stat/stat.ih0000644000175000017500000000035612222576540014364 0ustar frankfrank#include "stat" #include #include #include #include #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/stat/name.f0000644000175000017500000000007612223777441014161 0ustar frankfrankinline std::string const &Stat::name() { return d_name; } bobcat-3.19.01/stat/lastchange.f0000644000175000017500000000014212223777304015342 0ustar frankfrankinline DateTime Stat::lastChange() const { return DateTime(d_stat.st_ctime, DateTime::UTC); } bobcat-3.19.01/stat/init.cc0000644000175000017500000000023612224000414014316 0ustar frankfrank#include "stat.ih" void Stat::init() { d_errno = ::stat(d_name.c_str(), &d_stat) ? errno : 0; } bobcat-3.19.01/stat/operatorassign.cc0000644000175000017500000000014312222600571016420 0ustar frankfrank#include "stat.ih" Stat &Stat::operator=(Stat &&tmp) { fswap(*this, tmp); return *this; } bobcat-3.19.01/stat/stat0000644000175000017500000000734112223777767014005 0ustar frankfrank#ifndef INCLUDED_BOBCAT_STAT_ #define INCLUDED_BOBCAT_STAT_ #include #include #include #include #include #include namespace FBB { class User; class Stat: public GS__ { struct stat d_stat; bool d_errno; std::string d_name; public: typedef struct stat stat; // Defines Stat::stat for clients enum Combine { ALL, ANY, }; enum SpecialMode { SUID = 04000, SGID = 02000, SB = 01000, }; enum Mode { UR = 0400, UW = 0200, UX = 0100, GR = 040, GW = 020, GX = 010, OR = 04, OW = 02, OX = 01, READ = UR | GR | OR, WRITE = UW | GW | OW, EXEC = UX | GX | OX, RWX = 0777, }; Stat(); // 1 explicit Stat(std::string const &name); // 2 Stat(std::string const &name, std::string const &pathlist); // 1.f Stat(Stat &&tmp); // 3 Stat &operator=(Stat const &other) = default; Stat &operator=(Stat &&tmp); bool access(User const &user, size_t mode, bool useEffective = true) const; DateTime lastAccess() const; // .f DateTime lastChange() const; // .f DateTime lastModification() const; // .f Type type() const; // .f bool isType(Type probe); // .f bool mode(size_t mode, Combine combi = ALL) const; bool set(std::string const &name); bool set(std::string const &name, std::string const &pathlist); bool specialMode(size_t specialMode, Combine combi = ALL) const; off_t size() const; // .f operator bool() const; // .f size_t blockSize() const; // .f size_t device() const; // .f size_t deviceType() const; // .f size_t error() const; // .f size_t gid() const; // .f size_t inode() const; // .f size_t mode() const; // .f size_t nBlocks() const; // .f size_t nLinks() const; // .f size_t uid() const; // .f stat const &statStruct() const; // .f std::string const &name(); // .f std::string modeStr() const; std::string path(); std::string typeStr() const; private: void init(); }; #include "stat1.f" #include "blocksize.f" #include "device.f" #include "devicetype.f" #include "error.f" #include "gid.f" #include "inode.f" #include "istype.f" #include "lastaccess.f" #include "lastchange.f" #include "lastmodification.f" #include "mode.f" #include "name.f" #include "nblocks.f" #include "nlinks.f" #include "opbool.f" #include "size.f" #include "statstruct.f" #include "type.f" #include "uid.f" } // FBB #endif bobcat-3.19.01/stat/device.f0000644000175000017500000000011112223776737014475 0ustar frankfrankinline size_t Stat::device() const { return d_stat.st_dev; } bobcat-3.19.01/string/0000755000175000017500000000000012257325714013421 5ustar frankfrankbobcat-3.19.01/string/argv.cc0000644000175000017500000000041012222600701014642 0ustar frankfrank#include "string.ih" char const **String::argv(std::vector const &lines) { size_t idx = lines.size(); char const **ret = new char const *[idx + 1]; ret[idx] = 0; for (; idx--; ) ret[idx] = lines[idx].c_str(); return ret; } bobcat-3.19.01/string/tolower.f0000644000175000017500000000010512223023055015241 0ustar frankfrankinline void String::tolower(char &chr) { chr = ::tolower(chr); } bobcat-3.19.01/string/escape1.cc0000644000175000017500000000107412222600701015233 0ustar frankfrank#include "string.ih" string String::escape(string const &str, char const *series) { string ret; string::size_type left = 0; while (true) { string::size_type right = str.find_first_of(series, left); ret += str.substr(left, right - left); // append until separator if (right == string::npos) // done when all copied return ret; ret += "\\"; // append backslash ret += str[right]; // append the special char left = right + 1; } } bobcat-3.19.01/string/separator1.cc0000644000175000017500000000113112222600701015765 0ustar frankfrank#include "string.ih" // We're at a separator. Return the iterator pointing beyond the // separator. find_first_not_of() will do that, unless there are no // non-blanks anymore. In that case, find_first_pos() returns npos, // and end() must be returned. String::ConstIter String::separator(string const &str, ConstIter from, string const &separators) { string::size_type idx = str.find_first_not_of(separators, from - str.begin()); return idx == string::npos ? str.end() : str.begin() + idx; } bobcat-3.19.01/string/quotedstring.cc0000644000175000017500000000153012222600701016437 0ustar frankfrank#include "string.ih" // On entry, `begin' points at the beginning of the quoted string, on exit, // the quoted string (without the surrounding quotes) is returned, and 'begin' // points to the location immediately following the last quote. // // A single quoted string does not do \-escapes. String::SplitPair String::quotedString(ConstIter &begin, ConstIter const &end) { SplitPair ret(string(), SQUOTE); while (true) { if (++begin == end) { ret.second = SQUOTE_UNTERMINATED; return ret; } if (*begin == '\'') // stop at the next single quote { ++begin; // skip it return ret; // and return the string's contents } ret.first += *begin; // otherwise add the next char } } bobcat-3.19.01/string/casecmp.f0000644000175000017500000000020012223023055015155 0ustar frankfrankinline int String::casecmp(std::string const &lhs, std::string const &rhs) { return strcasecmp(lhs.c_str(), rhs.c_str()); } bobcat-3.19.01/string/dquotedstring.cc0000644000175000017500000000265112222600701016610 0ustar frankfrank#include "string.ih" // On entry, `begin' points at the beginning of the double quoted string, // on exit, the unescaped double quoted string (without the surrounding double // quotes) is returned, and 'begin' points to the location immediately // following the last double quote. String::SplitPair String::dquotedString(ConstIter &begin, ConstIter const &end) { SplitPair ret(string(), DQUOTE); while (true) { if (++begin == end) { ret.second = DQUOTE_UNTERMINATED; return ret; } switch (*begin) { default: // regular characters are added to ret ret.first += *begin; break; case '\\': // backslash: accept it and accept the next char ret.first += '\\'; if (begin + 1 == end) // the \ was the last character break; // causing an error at the loop's top ret.first += *++begin; // add the char beyond the \-char break; case '"': // closing double quote observed ++begin; // skip it // return the unescaped double quoted string's // contents ret.first = String::unescape(ret.first); return ret; } } } bobcat-3.19.01/string/string.ih0000644000175000017500000000031612223023055015233 0ustar frankfrank#include "string" #include #include #include #include #include using namespace std; using namespace FBB; #include "tolower.f" #include "toupper.f" bobcat-3.19.01/string/toupper.f0000644000175000017500000000010512223023055015244 0ustar frankfrankinline void String::toupper(char &chr) { chr = ::toupper(chr); } bobcat-3.19.01/string/split5.cc0000644000175000017500000000530412222600701015132 0ustar frankfrank#include "string.ih" /* Each character of the String is inspected in turn. The following situations are recognized: The character is in the set of separators: If currently constructing an element, the element is finished, and the first non-separator is searched. The thus recognized separator is handled next. The character is a double quote: If not currently constructing an element, read all subsequent characters until a matching dquote is found. If, while doing so, an escape character is encountered, then add the escape char and the char following the escape char. Handle the recognized dquoted string next. If currently constructing an element, add the dquote to the current element. If the end-of-string is encountered, flag an error. The character is a single quote: If not currently constructing an element, read all subsequent characters until a matching squote is found. If, while doing so, an escape character is encountered, then add the escape char and the char following the escape char. Handle the recognized squoted string next. If currently constructing an element, add the squote to the current element. If the end-of-string is encountered, flag an error. The character is another character: If not currently constructing an element, read all subsequent characters until a separator or the end of the string is found. If, while doing so, escape character is encountered, then add the escape char and the char following the escape char. Handle the recognized squoted string next. */ size_t String::split(vector *words, string const &str, char const *sep, bool addEmpty) { words->clear(); ConstIter from = str.begin(); ConstIter beyond = str.end(); string separators(sep); ConstIter until; while (from != beyond) { Type type = nextField(str, &until, // get the from field, `until' from, separators); // points beyond the field's // last character // see if it is a quoted string bool quoted = (type == DQUOTE || type == SQUOTE); from += quoted; // skip the quote of quoted strings // add the field to `words' if (type != SEPARATOR || addEmpty) words->push_back(SplitPair(string(from, until), type)); // update from: skip the quote of quoted from = until + quoted; // strings } return words->size(); } bobcat-3.19.01/string/split3.cc0000644000175000017500000000101312222600701015121 0ustar frankfrank#include "string.ih" vector String::split(string const &str, string const &separators, bool addEmpty) { vector ret; // visit all chars of str for (ConstIter begin = str.begin(), end = str.end(); begin != end; ) { SplitPair next = split(begin, str.end(), separators); if (next.second == SEPARATOR && not addEmpty) continue; ret.push_back(next); } return ret; } bobcat-3.19.01/string/driver/0000755000175000017500000000000012222576537014717 5ustar frankfrankbobcat-3.19.01/string/driver/build0000755000175000017500000000121512222576537015743 0ustar frankfrank#!/bin/bash rm -f driver case $1 in (tmp) echo "g++ -c driver.cc" g++ --std=c++11 -I../../tmp -c driver.cc || exit 1 g++ -o driver driver.o -L../../tmp/lib -lbobcat ;; (lib) echo "g++ -c driver.cc" g++ --std=c++11 -I../../tmp -o driver.o -c driver.cc || exit 1 g++ -o driver driver.o -lbobcat ;; (*) echo " Usage: build tmp - build the driver using the shared library created in ../../tmp/lib build lib - build the driver using the shared bobcat library installed in the standard location for shared libs " exit 1 ;; esac bobcat-3.19.01/string/driver/splitdriver.cc0000644000175000017500000000101412222576537017571 0ustar frankfrank// compile with // gx splitdriver.cc -L ../tmp/ -lstring -lbobcat #include #include "../string" using namespace std; using namespace FBB; int main(int argc, char **argv) { while (true) { cout << "? "; string line; if (not getline(cin, line)) break; vector vect(String::split(line, " \t", argc == 1)); for (auto const &element: vect) cout << '`' << element.first << "': " << element.second << '\n'; } } bobcat-3.19.01/string/driver/driver.cc0000644000175000017500000000246712222576537016532 0ustar frankfrank/* driver.cc */ #include #include "../string" using namespace std; using namespace FBB; static char const *type[] = { "DQUOTE_UNTERMINATED", "SQUOTE_UNTERMINATED", "ESCAPED_END", "SEPARATOR", "NORMAL", "DQUOTE", "SQUOTE", }; int main(int argc, char **argv) { if (argc == 1) cout << "Provide an argument to suppress SEPARATOR fields\n"; while (true) { cout << "Enter a line, or empty line to stop: " << endl; string line; if (!getline(cin, line) || !line.length()) break; vector splitpair; cout << "Split into " << String::split(&splitpair, line, " \t", argc == 1) << " fields\n"; for ( vector::iterator it = splitpair.begin(); it != splitpair.end(); ++it ) cout << (it - splitpair.begin() + 1) << ": " << type[it->second] << ": `" << it->first << "', unescaped: `" << String::unescape(it->first) << "'\n"; cout << line << "Upper case: " << String::uc(line) << ", lc: " << String::lc(line) << '\n'; } } bobcat-3.19.01/string/split6.cc0000644000175000017500000000461212222600701015134 0ustar frankfrank#include "string.ih" String::SplitPair String::split(ConstIter &begin, ConstIter const &end, string const &separators) { SplitPair ret(string(), NORMAL); bool empty = true; for (; begin != end; ) { // saw a separator if (separators.find(*begin) != string::npos) { // non-empty strings: keep the sep. // for the next call if (empty) // empty strings: return an empty { // string, and the SEPARATOR indicator ret.second = SEPARATOR; ++begin; // to the next char } break; // end the for-loop, finding } // `return ret' at the end empty = false; switch (*begin) { case '"': // dquoted string: accept all until the { // next, and then do unescape. SplitPair const &part = dquotedString(begin, end); ret.first += part.first; if (part.second == DQUOTE_UNTERMINATED) { ret.second = DQUOTE_UNTERMINATED; return ret; } } break; case '\'': // quoted string: accept all until { // the next ', without unescaping SplitPair const &part = quotedString(begin, end); ret.first += part.first; if (part.second == SQUOTE_UNTERMINATED) { ret.second = SQUOTE_UNTERMINATED; return ret; } } break; case '\\': // unescape a lone escape sequence { IntType part(escapedString(begin, end)); ret.first += part.first; if (part.second == ESCAPED_END) { ret.second = ESCAPED_END; return ret; } } break; default: // add remaining chars to the next element ret.first += *begin++; break; } } return ret; } bobcat-3.19.01/string/trim1.cc0000644000175000017500000000047412222600701014751 0ustar frankfrank#include "string.ih" string String::trim(string const &str) { string::size_type idx = str.find_first_not_of(" \t\r\n"); // find first non-ws if (idx == string::npos) // only ws chars? return string(); return str.substr(idx, str.find_last_not_of(" \t\r\n") - idx + 1); } bobcat-3.19.01/string/unescape1.cc0000644000175000017500000000631712222600701015603 0ustar frankfrank#include "string.ih" namespace { char const escapeChars[] = "abfnrtv"; char const escapeValue[] = {'\a', '\b', '\f', '\n', '\r', '\t', '\v'}; size_t handleOctal(string *dest, string const &src, size_t pos) { size_t pos2 = min(src.length(), src.find_first_not_of("01234567", pos)); if (pos2 == pos + 1 && src[pos] == '0') // saw \0 { *dest += static_cast(0); return pos2; } size_t const nOct = 3; // need exactly 3 octals pos2 = min(pos + nOct, pos2); if (pos2 != pos + nOct) // need exactly nOct octals { *dest += src[pos]; // add next char if not so return pos + 1; // next to handle } A2x a2x(src.substr(pos, nOct)); size_t ch; a2x >> oct >> ch; // convert substr. to octal *dest += static_cast(ch); // append the octal value return pos2; // pos. of next to handle } size_t handleHex(string *dest, string const &src, size_t pos) { size_t const nHex = 2; // need exactly 2 hex digits ++pos; // skip the 'x' size_t pos2 = min(pos + nHex, src.find_first_not_of( "0123456789abcdefABCDEF", pos)); if (pos2 != pos + nHex) // found a hex character? { *dest += src[pos - 1]; // add next char if so return pos; // next char to handle } A2x a2x(src.substr(pos, nHex)); size_t ch; a2x >> hex >> ch; // convert substr. to hex *dest += static_cast(ch); // append the hex value return pos2; // pos. of next to handle } } string String::unescape(string const &str) { string ret; size_t prefix = 0; // prefix text before \-char size_t pos = 0; while (true) { pos = str.find('\\', pos); ret += str.substr(prefix, pos - prefix);// append prefix if (pos == string::npos) // done if no more \-chars return ret; ++pos; // skip \-char if (pos == str.length()) // \-char terminates: remove it return ret; // since we're removing \-chars int next = str[pos]; // determine next char if (char const *cp = strchr(escapeChars, next))// escape sequence ? { ret += escapeValue[cp - escapeChars];// then assign escape char ++pos; // next character to handle } else if (strchr("01234567", next)) // handle octal values pos = handleOctal(&ret, str, pos); else if (next == 'x') // handle hex values pos = handleHex(&ret, str, pos); else // handle lone characters ret += str[pos++]; prefix = pos; } } bobcat-3.19.01/string/split4.cc0000644000175000017500000000234012222600701015126 0ustar frankfrank#include "string.ih" size_t String::split(std::vector *words, string const &str, char const *sep, bool addEmpty) { words->clear(); ConstIter from = str.begin(); ConstIter beyond = str.end(); string separators(sep); ConstIter until; while (from != beyond) { //cerr << "SCAN `" << string(from, beyond) << "'" << endl; Type type = nextField(str, &until, from,// get the from field, `until' separators); // points beyond the field's // last character //cerr << "\tFIELD: `" << string(from, until) << "'" << endl; //cerr << "\tBEYOND: `" << string(until, beyond) << "'" << endl; // see if it is a quoted string bool quoted = (type == DQUOTE || type == SQUOTE); from += quoted; // skip the quote of quoted strings // add the field to `words' if (type != SEPARATOR || addEmpty) words->push_back(string(from, until)); // update from: skip the quote of quoted from = until + quoted; // strings } return words->size(); } bobcat-3.19.01/string/quoted1.cc0000644000175000017500000000156212222600701015276 0ustar frankfrank#include "string.ih" String::ConstIter String::quoted(string const &str, ConstIter from, int quote) { ConstIter beyond = str.end(); while (true) { ++from; // skip the quote or next character if (from == beyond) // missed the matching closing quote: return from; // return, let the caller handle this // problem if (*from == quote) // matched quote found: done return from; if (*from == '\\') // handle the backslash: skip the next { // char if (++from == beyond) // oops, there's no next char: let the return from; // caller handle the non-terminated } // string. } } bobcat-3.19.01/string/nextfield1.cc0000644000175000017500000000267412222600701015764 0ustar frankfrank#include "string.ih" String::Type String::nextField(string const &str, ConstIter *until, ConstIter from, string const &separators) { if (separators.find(*from) != string::npos) // saw a separator { // get it, `*until' points *until = separator(str, from, separators); // beyond it. return SEPARATOR; } switch (*from) // handle all other cases { case '"': // d-quoted string *until = quoted(str, from, '"'); // if pointing at the matching // " then it's ok, otherwise // an error was encountered return *until != str.end() ? DQUOTE : DQUOTE_UNTERMINATED; case '\'': *until = quoted(str, from, '\''); // if pointing at the matching // ' then it's ok, otherwise // an error was encountered return *until != str.end() ? SQUOTE : SQUOTE_UNTERMINATED; default: // otherwise get the next word return word(str, until, from, separators); } } bobcat-3.19.01/string/split1.cc0000644000175000017500000000135112222600701015124 0ustar frankfrank#include "string.ih" vector String::split(Type *type, string const &str, string const &separators, bool addEmpty) { vector ret; Type localType = NORMAL; // visit all chars of str for (ConstIter begin = str.begin(), end = str.end(); begin != end; ) { SplitPair next = split(begin, str.end(), separators); if (next.second == SEPARATOR && not addEmpty) continue; ret.push_back(next.first); localType = next.second; } if (type) *type = localType == DQUOTE || localType == SQUOTE || localType == SEPARATOR ? NORMAL : localType; return ret; } bobcat-3.19.01/string/string0000644000175000017500000000641112223023055014636 0ustar frankfrank#ifndef INCLUDED_BOBCAT_STRING_ #define INCLUDED_BOBCAT_STRING_ #include #include #include #include namespace FBB { struct String { enum Type { DQUOTE_UNTERMINATED, // unterminated d-quoted element SQUOTE_UNTERMINATED, // unterminated s-quoted element ESCAPED_END, // word with plain \ at the end SEPARATOR, // separator encountered NORMAL, // normal string-element in the original string DQUOTE, // string-element originally surrounded by " chars SQUOTE, // string-element originally surrounded by ' chars }; typedef std::pair SplitPair; static char const **argv(std::vector const &lines); static int casecmp(std::string const &lhs, std::string const &rhs); // .f static std::string lc(std::string const &str); static std::vector // 1 split(Type *type, std::string const &str, std::string const &separators = " \t", bool addEmpty = false); static std::vector // 3 split(std::string const &str, std::string const &separators = " \t", bool addEmpty = false); static size_t split(std::vector *words, // 4 std::string const &str, char const *separators = " \t", bool addEmpty = false); // 5 static size_t split(std::vector *words, std::string const &str, char const *separators = " \t", bool addEmpty = false); static std::string trim(std::string const &str); static std::string uc(std::string const &str); static std::string unescape(std::string const &str); static std::string escape(std::string const &str, char const *series = "'\"\\"); private: typedef std::string::const_iterator ConstIter; typedef std::pair IntType; // used by split1..3.cc static SplitPair split(ConstIter &begin, ConstIter const &end, // 6 std::string const &separators); static SplitPair dquotedString(ConstIter &begin, ConstIter const &end); static SplitPair quotedString(ConstIter &begin, ConstIter const &end); static IntType escapedString(ConstIter &begin, ConstIter const &end); static Type nextField(std::string const &str, ConstIter *until, ConstIter from, std::string const &separators); static ConstIter separator(std::string const &str, ConstIter from, std::string const &separators); static ConstIter quoted(std::string const &str, ConstIter from, int quote); static Type word(std::string const &str, ConstIter *until, ConstIter from, std::string const &separators); static void tolower(char &chr); // .f static void toupper(char &chr); // .f }; #include "casecmp.f" } // FBB #endif bobcat-3.19.01/string/word1.cc0000644000175000017500000000207212222600701014745 0ustar frankfrank#include "string.ih" // type should have been initialized to `NORMAL' by the caller String::Type String::word(string const &str, ConstIter *until, ConstIter from, string const &separators) { ConstIter beyond = str.end(); while (true) { ++from; // accept the first (and next) character if ( from == beyond // at the end or at a separator || separators.find(*from) != string::npos ) { *until = from; // indicate the word's end return NORMAL; // and a normal word } if (*from == '\\') // handle the backslash: skip the next { // char if (++from == beyond) // oops, there's no next char. { *until = from; // return anyway return ESCAPED_END; // but indicate that it's an abnormal } // word } } } bobcat-3.19.01/string/escapedstring.cc0000644000175000017500000000220112222600701016536 0ustar frankfrank#include "string.ih" // On entry, `begin' points at the beginning of the stand-alone escape // character. // On exit, the character is unescaped and returned, and `begin' points // immediately beyond the characters defining the escape-sequence. String::IntType String::escapedString(ConstIter &begin, ConstIter const &end) { IntType ret(0, NORMAL); if (begin + 1 == end) // at least one char. should follow { ret = IntType('\\', ESCAPED_END); ++begin; return ret; } string escaped(begin, end); // local copy of the escaped text // cut the copy at the next backslash escaped = escaped.substr(0, escaped.find('\\', 1)); size_t preLength = escaped.length(); // unescape the escape-sequence escaped = String::unescape(escaped); // reposition begin beyond the chars of // the escape sequence begin += 1 + preLength - escaped.length(); ret.first = escaped[0]; // return the escaped character return ret; } bobcat-3.19.01/string/lc1.cc0000644000175000017500000000022312222600701014364 0ustar frankfrank#include "string.ih" string String::lc(string const &str) { string ret(str); for (auto &ch: ret) tolower(ch); return ret; } bobcat-3.19.01/string/uc1.cc0000644000175000017500000000022412222600701014376 0ustar frankfrank#include "string.ih" string String::uc(string const &lhs) { string ret(lhs); for (auto &ch: ret) toupper(ch); return ret; } bobcat-3.19.01/stringline/0000755000175000017500000000000012223321015014250 5ustar frankfrankbobcat-3.19.01/stringline/stringline.ih0000644000175000017500000000010112222576537016764 0ustar frankfrank#include "stringline" using namespace std; using namespace FBB; bobcat-3.19.01/stringline/stringline0000644000175000017500000000035612223321015016355 0ustar frankfrank#ifndef INCLUDED_BOBCAT_STRINGLINE_ #define INCLUDED_BOBCAT_STRINGLINE_ #include #include namespace FBB { struct StringLine: public std::string {}; #include "opextract.f" // istream >> StringLine } // FBB #endif bobcat-3.19.01/stringline/opextract.f0000644000175000017500000000014412223321004016425 0ustar frankfrankinline std::istream &operator>>(std::istream &in, StringLine &str) { return getline(in, str); } bobcat-3.19.01/symcryptstreambufbase/0000755000175000017500000000000012257325714016551 5ustar frankfrankbobcat-3.19.01/symcryptstreambufbase/checkoutbufsize.cc0000644000175000017500000000053312222576535022257 0ustar frankfrank#include "symcryptstreambufbase.ih" void SymCryptStreambufBase::checkOutBufSize(size_t inputSize) { size_t outBufSize = (inputSize + d_blockSize - 1) / d_blockSize * d_blockSize; if (outBufSize > d_outBufSize) d_outBuf.reset(new char[d_outBufSize = outBufSize]); } bobcat-3.19.01/symcryptstreambufbase/symcryptstreambufbase.ih0000644000175000017500000000022112222576535023525 0ustar frankfrank#include "symcryptstreambufbase" #include #include using namespace std; using namespace FBB; using namespace IUO; bobcat-3.19.01/symcryptstreambufbase/symcryptstreambufbase0000644000175000017500000000335012222576535023134 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SYMCRYPTSTREAMBUFBASE_ #define INCLUDED_BOBCAT_SYMCRYPTSTREAMBUFBASE_ #include #include #include #include #include namespace FBB { namespace IUO // the facilities defined here are not further documented: { // the SymCryptStreambufBase class defined below should be // used by ISymCryptStreambuf only. class SymCryptStreambufBase: public FBB::IFilterStreambuf { EVP_CIPHER_CTX d_ctx; size_t d_inBufSize; size_t d_blockSize; size_t d_outBufSize = 0; bool d_allDone = false; std::istream &d_in; int (*d_evpUpdate)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, unsigned char const *in, int inl); int (*d_evpFinal_ex)(EVP_CIPHER_CTX *, unsigned char *out, int *outl); std::unique_ptr d_outBuf; std::unique_ptr d_inBuf; public: SymCryptStreambufBase( int (*evpInit)(EVP_CIPHER_CTX *, EVP_CIPHER const *, ENGINE *impl, unsigned char const *key, unsigned char const *iv), int (*evpUpdate)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, unsigned char const *in, int inl), int (*evpFinal)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl), std::istream &in, char const *type, std::string const &key, std::string const &iv, size_t bufSize, size_t filterBufSize, ENGINE *engine ); private: bool filter(char const **srcBegin, char const **srcEnd) override; void checkOutBufSize(size_t inputSize); }; } // IUO } // FBB #endif bobcat-3.19.01/symcryptstreambufbase/symcryptstreambufbase1.cc0000644000175000017500000000300612222576535023577 0ustar frankfrank#include "symcryptstreambufbase.ih" SymCryptStreambufBase::SymCryptStreambufBase( int (*evpInit_ex)(EVP_CIPHER_CTX *, EVP_CIPHER const *, ENGINE *, unsigned char const *key, unsigned char const *iv), int (*evpUpdate)(EVP_CIPHER_CTX *, unsigned char *out, int *outl, unsigned char const *in, int inl), int (*evpFinal_ex)(EVP_CIPHER_CTX *, unsigned char *out, int *outl), std::istream &in, char const *type, std::string const &keyParam, std::string const &ivParam, size_t bufSize, size_t filterBufSize, ENGINE *engine ) : IFilterStreambuf(filterBufSize), d_inBufSize(bufSize < 100 ? 100 : bufSize), d_in(in), d_evpUpdate(evpUpdate), d_evpFinal_ex(evpFinal_ex), d_inBuf(new char[d_inBufSize]) { OpenSSL_add_all_ciphers(); EVP_CIPHER const *cipherType = 0; if (type) cipherType = EVP_get_cipherbyname(type); if (cipherType == 0) throw Exception() << "FBB::ISymCryptStreambuf: cipher " << (type ? type : "0") << " not available"; string key(keyParam); key.resize(EVP_MAX_KEY_LENGTH); string iv(ivParam); iv.resize(EVP_MAX_IV_LENGTH); EVP_CIPHER_CTX_init(&d_ctx); (*evpInit_ex)(&d_ctx, cipherType, engine, reinterpret_cast(key.data()), reinterpret_cast(iv.data())); d_blockSize = EVP_CIPHER_CTX_block_size(&d_ctx); } bobcat-3.19.01/symcryptstreambufbase/filter.cc0000644000175000017500000000164612222576535020355 0ustar frankfrank#include "symcryptstreambufbase.ih" #include bool SymCryptStreambufBase::filter(char const **srcBegin, char const **srcEnd) { if (d_allDone) return false; d_in.read(d_inBuf.get(), d_inBufSize); size_t inBufRead = d_in.gcount(); // we got this many checkOutBufSize(inBufRead); int outBufSize; (*d_evpUpdate)( &d_ctx, reinterpret_cast(d_outBuf.get()), &outBufSize, reinterpret_cast(d_inBuf.get()), inBufRead ); if (outBufSize == 0) { // encryption checkOutBufSize(d_blockSize); (*d_evpFinal_ex)( &d_ctx, reinterpret_cast(d_outBuf.get()), &outBufSize ); d_allDone = true; } *srcBegin = d_outBuf.get(); *srcEnd = *srcBegin + outBufSize; return outBufSize; } bobcat-3.19.01/syslogbuf/0000755000175000017500000000000012257325714014130 5ustar frankfrankbobcat-3.19.01/syslogbuf/setdefaultpriority.cc0000644000175000017500000000024712222576523020402 0ustar frankfrank#include "syslogbuf.ih" Priority Syslogbuf::setDefaultPriority(Priority priority) { Priority old = d_orgPriority; d_orgPriority = priority; return old; } bobcat-3.19.01/syslogbuf/syslogbuf0000644000175000017500000000755012226236065016073 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SYSLOGBUF_ #define INCLUDED_BOBCAT_SYSLOGBUF_ /* options (default: none): LOG_CONS write directly to system console if there is an error while sending to system logger LOG_NDELAY open the connection immediately (normally, the con- nection is opened when the first message is logged) LOG_PERROR print to stderr as well LOG_PID include PID with each message facility type of program doing the logging. LOG_USER is used as default: LOG_AUTHPRIV security/authorization messages (private) LOG_CRON clock daemon (cron and at) LOG_DAEMON other system daemons LOG_KERN kernel messages LOG_LOCAL0 through LOG_LOCAL7 reserved for local use LOG_LPR line printer subsystem LOG_MAIL mail subsystem LOG_NEWS USENET news subsystem LOG_SYSLOGBUF messages generated internally by syslogbufd LOG_USER(default) generic user-level messages LOG_UUCP UUCP subsystem level (priority): LOG_NOTICE is used by default. This determines the importance of the message. The levels are, in order of decreasing importance: LOG_EMERG system is unusable LOG_ALERT action must be taken immediately LOG_CRIT critical conditions LOG_ERR error conditions LOG_WARNING warning conditions LOG_NOTICE (Used as DEFAULT) normal, but significant, condition LOG_INFO informational message LOG_DEBUG debug-level message */ #include #include #include namespace FBB { enum Priority { NOTICE = LOG_NOTICE, EMERG = LOG_EMERG, ALERT = LOG_ALERT, CRIT = LOG_CRIT, ERR = LOG_ERR, WARNING = LOG_WARNING, INFO = LOG_INFO, DEBUG = LOG_DEBUG, }; enum PriorityType { SINGLE, UPTO }; enum Facility { AUTHPRIV = LOG_AUTHPRIV, CRON = LOG_CRON, DAEMON = LOG_DAEMON, KERN = LOG_KERN, LOCAL0 = LOG_LOCAL0, LOCAL1 = LOG_LOCAL1, LOCAL2 = LOG_LOCAL2, LOCAL3 = LOG_LOCAL3, LOCAL4 = LOG_LOCAL4, LOCAL5 = LOG_LOCAL5, LOCAL6 = LOG_LOCAL6, LOCAL7 = LOG_LOCAL7, LPR = LOG_LPR, MAIL = LOG_MAIL, NEWS = LOG_NEWS, USER = LOG_USER, UUCP = LOG_UUCP, }; class Syslogbuf: public std::streambuf { struct Data; Priority d_priority; Priority d_orgPriority; Data *d_data; public: explicit Syslogbuf(std::string const &ident = "", Priority priority = NOTICE, Facility facility = USER, int option = 0); explicit Syslogbuf(char const *ident, Priority priority = NOTICE, Facility facility = USER, int option = 0); ~Syslogbuf(); void open(std::string const &ident, Priority priority = NOTICE, Facility facility = USER, int option = 0); void close(); Priority defaultPriority() const; // .f Priority priority() const; // .f Priority setDefaultPriority(Priority priority); Priority setPriority(Priority priority); protected: int pSync(); private: virtual int sync(); virtual int overflow(int c); void reset(std::string const &ident, Facility facility, int option); }; #include "defaultpriority.f" #include "priority.f" } // FBB #endif bobcat-3.19.01/syslogbuf/destructor.cc0000644000175000017500000000010712222576523016631 0ustar frankfrank#include "syslogbuf.ih" Syslogbuf::~Syslogbuf() { close(); } bobcat-3.19.01/syslogbuf/priority.f0000644000175000017500000000011112223321270016133 0ustar frankfrankinline Priority Syslogbuf::priority() const { return d_priority; } bobcat-3.19.01/syslogbuf/open.cc0000644000175000017500000000036112222576523015376 0ustar frankfrank#include "syslogbuf.ih" void Syslogbuf::open(std::string const &ident, Priority priority, Facility facility, int option) { close(); d_orgPriority = d_priority = priority; reset(ident, facility, option); } bobcat-3.19.01/syslogbuf/syslogbuf.ih0000644000175000017500000000021412226236051016453 0ustar frankfrank#include "syslogbuf" using namespace std; using namespace FBB; struct Syslogbuf::Data { std::string ident; std::string buffer; }; bobcat-3.19.01/syslogbuf/syslogbuf2.cc0000644000175000017500000000030712222576523016534 0ustar frankfrank#include "syslogbuf.ih" Syslogbuf::Syslogbuf(char const *ident, Priority priority, Facility facility, int option) : Syslogbuf(string(ident), priority, facility, option) {} bobcat-3.19.01/syslogbuf/overflow.cc0000644000175000017500000000025312222576523016300 0ustar frankfrank#include "syslogbuf.ih" int Syslogbuf::overflow(int c) { if (c != EOF) d_data->buffer += static_cast(c); else sync(); return c; } bobcat-3.19.01/syslogbuf/defaultpriority.f0000644000175000017500000000012312223321227017505 0ustar frankfrankinline Priority Syslogbuf::defaultPriority() const { return d_orgPriority; } bobcat-3.19.01/syslogbuf/reset.cc0000644000175000017500000000041012222576523015552 0ustar frankfrank#include "syslogbuf.ih" void Syslogbuf::reset(string const &ident, Facility facility, int option) { delete d_data; d_data = new Data{ident}; openlog(d_data->ident.c_str(), option, facility); setp(0, 0); // no buffer yet } bobcat-3.19.01/syslogbuf/syslogbuf1.cc0000644000175000017500000000041412222576523016532 0ustar frankfrank#include "syslogbuf.ih" Syslogbuf::Syslogbuf(std::string const &ident, Priority priority, Facility facility, int option) : d_priority(priority), d_orgPriority(priority), d_data(0) { reset(ident, facility, option); } bobcat-3.19.01/syslogbuf/setpriority.cc0000644000175000017500000000023212222576523017027 0ustar frankfrank#include "syslogbuf.ih" Priority Syslogbuf::setPriority(Priority priority) { Priority old = d_priority; d_priority = priority; return old; } bobcat-3.19.01/syslogbuf/psync.cc0000644000175000017500000000035512222576523015574 0ustar frankfrank#include "syslogbuf.ih" int Syslogbuf::pSync() { if (d_data->buffer.length()) { syslog(d_priority, "%s", d_data->buffer.c_str()); d_data->buffer.erase(); d_priority = d_orgPriority; } return 0; } bobcat-3.19.01/syslogbuf/sync.cc0000644000175000017500000000010712222576523015407 0ustar frankfrank#include "syslogbuf.ih" int Syslogbuf::sync() { return pSync(); } bobcat-3.19.01/syslogbuf/close.cc0000644000175000017500000000012412222576523015537 0ustar frankfrank#include "syslogbuf.ih" void Syslogbuf::close() { sync(); closelog(); } bobcat-3.19.01/syslogstream/0000755000175000017500000000000012257325714014647 5ustar frankfrankbobcat-3.19.01/syslogstream/syslogstream0000644000175000017500000001172012223326452017320 0ustar frankfrank#ifndef INCLUDED_BOBCAT_SYSLOGSTREAM_ #define INCLUDED_BOBCAT_SYSLOGSTREAM_ // options (default: none): // // LOG_CONS // write directly to system console if there is an // error while sending to system logger // // LOG_NDELAY // open the connection immediately (normally, the con- // nection is opened when the first message is logged) // // LOG_PERROR // print to stderr as well // // LOG_PID // include PID with each message // // // facility // type of program doing the logging. LOG_USER is used as default: // // LOG_AUTHPRIV // security/authorization messages (private) // // LOG_CRON // clock daemon (cron and at) // // LOG_DAEMON // other system daemons // // LOG_KERN // kernel messages // // LOG_LOCAL0 through LOG_LOCAL7 // reserved for local use // // LOG_LPR // line printer subsystem // // LOG_MAIL // mail subsystem // // LOG_NEWS // USENET news subsystem // // LOG_SYSLOG // messages generated internally by syslogd // // LOG_USER(default) // generic user-level messages // // LOG_UUCP // UUCP subsystem // // level (priority): // // LOG_NOTICE is used by default. // This determines the importance of the message. The levels // are, in order of decreasing importance: // // LOG_EMERG // system is unusable // // LOG_ALERT // action must be taken immediately // // LOG_CRIT // critical conditions // // LOG_ERR // error conditions // // LOG_WARNING // warning conditions // // LOG_NOTICE (Used as DEFAULT) // normal, but significant, condition // // LOG_INFO // informational message // // LOG_DEBUG // debug-level message #include #include #include namespace FBB { class SyslogStream: private Syslogbuf, public std::ostream { public: explicit SyslogStream(std::string const &ident = "", Priority priority = NOTICE, Facility facility = USER, int option = 0); explicit SyslogStream(char const *ident, Priority priority = NOTICE, Facility facility = USER, int option = 0); Priority priority() const; // .f Priority defaultPriority() const; // .f Priority setPriority(Priority priority); // .f Priority setDefaultPriority(Priority priority); // .f void open(std::string const &ident, // .f Priority priority = NOTICE, Facility facility = USER, int option = 0); void close(); // .f static Priority stoP(std::string const &name, Priority priority = NOTICE); static Facility stoF(std::string const &name, Facility facility = USER); static int setMask(Priority p1, PriorityType upTo); // 1.f static int setMask(Priority p1); // 2.f template static int setMask(Priority p1, Priorities ...ps); // 3.f // MANIPULATORS: static std::ostream &emerg(std::ostream &str); // .f static std::ostream &alert(std::ostream &str); // .f static std::ostream &crit(std::ostream &str); // .f static std::ostream &err(std::ostream &str); // .f static std::ostream &warning(std::ostream &str); // .f static std::ostream ¬ice(std::ostream &str); // .f static std::ostream &info(std::ostream &str); // .f static std::ostream &debug(std::ostream &str); // .f static std::ostream &strerrno(std::ostream &str); // .f private: static std::ostream &setPriority(std::ostream &str, Priority priority); static int maskValue(Priority p1); // 1.f template static int maskValue(Priority p1, Priorities ...ps); // 2.f static int setMask(int maskValue, PriorityType upTo); }; #include "alert.f" #include "close.f" #include "crit.f" #include "debug.f" #include "defaultpriority.f" #include "emerg.f" #include "err.f" #include "info.f" #include "notice.f" #include "open.f" #include "priority.f" #include "setdefaultpriority.f" #include "setmask1.f" #include "setmask2.f" #include "setmask3.f" #include "setpriority.f" #include "warning.f" // The following private inline members, must remain here as they are used by // the setMask member template #include "maskvalue1.f" #include "maskvalue2.f" #include "setmask4.f" } // FBB #endif bobcat-3.19.01/syslogstream/warning.f0000644000175000017500000000015012223325774016456 0ustar frankfrankinline std::ostream &SyslogStream::warning(std::ostream &str) { return setPriority(str, WARNING); } bobcat-3.19.01/syslogstream/syslogstream.ih0000644000175000017500000000016612222576523017726 0ustar frankfrank#include "syslogstream" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/syslogstream/syslogstream2.cc0000644000175000017500000000035412222576523017774 0ustar frankfrank#include "syslogstream.ih" SyslogStream::SyslogStream(char const *ident, Priority priority, Facility facility, int option) : SyslogStream(string(ident == 0 ? "" : ident), priority, facility, option) {} bobcat-3.19.01/syslogstream/open.f0000644000175000017500000000030712223325321015742 0ustar frankfrankinline void SyslogStream::open(std::string const &ident, Priority priority, Facility facility, int option) { Syslogbuf::open(ident, priority, facility, option); } bobcat-3.19.01/syslogstream/syslogstream1.cc0000644000175000017500000000035112222576523017770 0ustar frankfrank#include "syslogstream.ih" SyslogStream::SyslogStream(string const &ident, Priority priority, Facility facility, int option) : Syslogbuf(ident, priority, facility, option), std::ostream(this) {} bobcat-3.19.01/syslogstream/setmask2.f0000644000175000017500000000013512223321636016536 0ustar frankfrankinline int SyslogStream::setMask(Priority p1) { return setMask(maskValue(p1), SINGLE); } bobcat-3.19.01/syslogstream/setmask4.f0000644000175000017500000000040112223326377016543 0ustar frankfrankinline int SyslogStream::setMask(int maskValue, PriorityType upTo) { // if upTo, maskValue is 2**x, and all its lower bits are also raised return setlogmask(upTo == SINGLE ? maskValue : maskValue |= (maskValue - 1)); } bobcat-3.19.01/syslogstream/priority.f0000644000175000017500000000013612223325406016666 0ustar frankfrankinline Priority SyslogStream::priority() const { return Syslogbuf::priority(); } bobcat-3.19.01/syslogstream/maskvalue1.f0000644000175000017500000000011012223326270017046 0ustar frankfrankinline int SyslogStream::maskValue(Priority p1) { return 1 << p1; } bobcat-3.19.01/syslogstream/setdefaultpriority.f0000644000175000017500000000020412223325541020743 0ustar frankfrankinline Priority SyslogStream::setDefaultPriority(Priority priority) { return Syslogbuf::setDefaultPriority(priority); } bobcat-3.19.01/syslogstream/setpriority.f0000644000175000017500000000016612223325475017413 0ustar frankfrankinline Priority SyslogStream::setPriority(Priority priority) { return Syslogbuf::setPriority(priority); } bobcat-3.19.01/syslogstream/emerg.f0000644000175000017500000000014412223325603016102 0ustar frankfrankinline std::ostream &SyslogStream::emerg(std::ostream &str) { return setPriority(str, EMERG); } bobcat-3.19.01/syslogstream/strerrno.cc0000644000175000017500000000016112222576523017030 0ustar frankfrank#include "syslogstream.ih" ostream &SyslogStream::strerrno(ostream &str) { return str << strerror(errno); } bobcat-3.19.01/syslogstream/setmask3.f0000644000175000017500000000023112223023055016526 0ustar frankfranktemplate inline int SyslogStream::setMask(Priority p1, Priorities ...ps) { return setMask(maskValue(p1, ps ...), SINGLE); } bobcat-3.19.01/syslogstream/driver/0000755000175000017500000000000012222576523016140 5ustar frankfrankbobcat-3.19.01/syslogstream/driver/build0000755000175000017500000004272212222576523017174 0ustar frankfrank#!/usr/bin/icmake -qt/tmp/driver // script generated by the C++ icmake script version 2.03 /* Configurable defines for the build script: CLASSES: string of directory-names under which sources of classes are found. E.g., CLASSES = "class1 class2" All class-names must be stored in one string. If classes are removed from the CLASSES definition or if the names in the CLASSES definition are reordered, the compilation should start again from scratch. */ string CLASSES; void setClasses() { // ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE // Use the construction `CLASSES += "classname1 classname2";' etc. CLASSES += " "; } /* Default values for the following variables are found in $IM/default/defines.im BUILD_LIBRARY: define this if you want to create a library for the object modules. Undefined by default: so NO LIBRARY IS BUILT. This links ALL object files to a program, which is a faster process than linking to a library. But it can bloat the executable: all o-modules, rather than those that are really used, become part of the program's code. When defined as an EMPTY STRING, the static library libXXX.a is created: all programs linked to this library will themselves contain the code of the required object modules. This will result in code duplication over different programs linked to this library. When defined as a VERSION STRING, e.g., 1.0.4, a shared library libXXX.so.VERSION is constructed, as well as the links libXXX.so.MAINVERSION and libXXX.so (e.g. 1.0.0 creates libXXX.so.1.0.0, libXXX.so.1 and libXXX.so). Note that with a shared library, the library is always constructed fresh from the compiled object files. But programs linked to this library will SHARE the code stored in the shared library. These programs will therefore tend to be relatively small. Also note that `ldconfig -v' might be required after installing a shared library (libXXX.so) for the first time, so that the linker knows of its existence (in ld.so.cache) BUILD_PROGRAM: define if a program is to be built. If not defined, library maintenance is assumed (default: defined). COMPILER: The compiler to use. COPT: C-options used by COMPILER ECHO_REQUEST: ON (default) if command echoing is wanted, otherwise: set to OFF GDB: define if gdb-symbolic debug information is wanted (not defined by default) LIBS: Extra libraries used for linking LIBPATH: Extra library-searchpaths used for linking LOCAL_NAMESPACE:The namespace that you, the programmer, use yourself. USING: List of :-separated namespaces to be used in sources and .ih files, appearing in `using' directives. USING does NOT automatically include LOCAL_NAMESPACE: add your LOCAL_NAMESPACE name to this list if want a `using' directive for your own namespace as well. Note that namespaces are NOT part of the build-script: they are only listed below for convenience. When they must be altered, the defaults must be changed in $IM/default/defines.im RELINK: Defined by default, causing a program to be relinked every time the script is called. Do not define it if relinking should only occur if a source is compiled. No effect for library maintenance. Current values: */ //#define BUILD_LIBRARY "" #define BUILD_PROGRAM #define COMPILER "g++" #define COPT "-Wall" #define ECHO_REQUEST 1 //#define GDB "-g" #define LIBS "bobcat" #define LIBPATH "" // local namespace is: FBB // using-declarations generated for: std:FBB // NO CONFIGURABLE PARTS BELOW THIS LINE /* V A R S . I M */ string // contain options for cwd, // current WD libs, // extra libs, e.g., "-lrss -licce" libpath, // extra lib-paths, eg, "-L../rss" copt, // Compiler options lopt, // Linker options libxxx, // full library-path libso, // symbolic link to so.major library path libsomajor, // lib.so.major path ofiles, // wildcards for o-files sources, // sources to be used current; // contains name of current dir. int nClasses, // number of classes/subdirectories program, // 1: program is built so_lib; // 1: so_lib is built list classes; // list of classes/directories /* parser.im */ void parser() { #ifdef GRAMBUILD chdir("parser/gramspec"); system("grambuild"); chdir(".."); if ( exists("grammar") && "grammar" younger "parser.cc" ) // new parser needed { exec("bison++", "-d", "-o", "parser.cc", "grammar"); printf("Note: the compilation of parser.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* S C A N N E R . I M */ void scanner() { string interactive; #ifdef INTERACTIVE interactive = "-I"; #endif #ifdef GRAMBUILD chdir("scanner"); if ( // new lexer needed exists("lexer") && ( "lexer" younger "yylex.cc" || "../parser/parser.h" younger "yylex.cc" ) ) { exec("flex++", interactive, "-oyylex.cc", "lexer"); printf("Note: the compilation of yylex.cc may produce " "several compiler warnings.\n"); } chdir(".."); #endif } /* I N I T I A L . I M */ void initialize() { echo(ECHO_REQUEST); sources = "*.cc"; ofiles = "o/*.o"; // std set of o-files copt = COPT; #ifdef GDB copt += " " + GDB; #endif #ifdef BUILD_PROGRAM program = 1; so_lib = 0; #else program = 0; #endif; #ifdef BUILD_LIBRARY if (strlen(BUILD_LIBRARY)) so_lib = !program; else so_lib = 0; #else if (!program) { printf("no program, no library ?\n"); exit(1); } #endif if (so_lib) copt += " -fPIC"; cwd = chdir("."); #ifdef GRAMBUILD CLASSES = "parser scanner "; if (exists("parser")) // subdir parser exists parser(); if (exists("scanner")) // subdir scannerexists scanner(); #endif setClasses(); // remaining classes classes = strtok(CLASSES, " "); // list of classes nClasses = sizeof(classes); } /* O B J F I L E S . I M */ list objfiles(list files) { string file, objfile; int i; for (i = 0; i < sizeof(files); i++) { file = element(i, files); // determine element of the list objfile = "./o/" + change_ext(file, "o"); // make obj-filename if (objfile younger file) // objfile is younger { files -= (list)file; // remove the file from the list i--; // reduce i to test the next } } return (files); } /* A L T E R E D . I M */ list altered(list files, string target) { int i; string file; for (i = 0; i < sizeof(files); i++) // try all elements of the list { file = element(i, files); // use element i of the list if (file older target) // a file is older than the target { files -= (list)file; // remove the file from the list i--; // reduce i to inspect the next } // file of the list } return (files); // return the new list } /* F I L E L I S T . I M */ list file_list(string type, string library) { list files; files = makelist(type); // make all files of certain type #ifdef BUILD_LIBRARY if (!so_lib) // keep all files with so libs files = altered(files, library);// keep all files newer than lib. #endif files = objfiles(files); // remove if younger .obj exist return (files); } /* L I N K . I M */ void link(string library, string exe) { printf("\n"); exec(COMPILER, "-o", exe, #ifdef BUILD_LIBRARY "-l" + library, #else ofiles, #endif libs, #ifdef GRAMBUILD "-lfl", #endif "-L.", libpath, lopt #ifndef GDB , "-s" #endif ); printf("ok: ", exe, "\n"); } /* P R E F I X C L . I M */ void prefix_class(string class_id) { list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, class_id + o_file); chdir(".."); } /* R M C L A S S P . I M */ #ifdef BUILD_LIBRARY string rm_class_id(string class_id, string ofile) { string ret; int index, n; n = strlen(ofile); for (index = strlen(class_id); index < n; index++) ret += element(index, ofile); return ret; } #endif void rm_class_prefix(string class_id) { #ifdef BUILD_LIBRARY list o_files; string o_file; int i; chdir("o"); o_files = makelist("*.o"); for (i = 0; o_file = element(i, o_files); i++) exec("mv", o_file, rm_class_id(class_id, o_file)); chdir(".."); #endif } /* L I N K S O . I M */ void link_solib(string library) { string gdb; #ifdef GDB gdb = GDB; #endif #ifdef BUILD_LIBRARY int index; list sofiles, version; version = strtok(BUILD_LIBRARY, "."); libso = "lib" + library + ".so"; libxxx = libso + "."; libsomajor = libxxx + element(0, version); libxxx += BUILD_LIBRARY; for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir(current); // chdir to a class directory. prefix_class((string)index); chdir(cwd); // go back to parent dir } if (!makelist("o/*.o")) ofiles = "*/o/*.o"; printf("\n"); exec(COMPILER, gdb, "-shared", "-Wl,-soname," + libsomajor, "-o", libxxx, ofiles, libs, "-L.", libpath, lopt ); printf("ok: ", libxxx, "\n"); for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir(current); // chdir to a class directory. rm_class_prefix((string)index); chdir(cwd); // go back to parent dir } exec("ln", "-sf", libxxx, libsomajor); printf("ok: ", libsomajor, "\n"); exec("ln", "-sf", libsomajor, libso); printf("ok: ", libso, "\n"); #endif } /* C C O M P I L E . I M */ void c_compile(list cfiles) { string nextfile; int i; if (!exists("o")) system("mkdir o"); if (sizeof(cfiles)) // files to compile ? { printf("\ncompiling: ", current, "\n\n"); // compile all files separately for (i = 0; nextfile = element(i, cfiles); i++) exec(COMPILER, "-c -o o/" + change_ext(nextfile, "o"), copt, nextfile); printf("\n"); } printf("ok: ", current, "\n"); } /* U P D A T E L I . I M */ void updatelib(string library) { #ifdef BUILD_LIBRARY list arlist, objlist; string to, from; objlist = makelist("o/*.o"); if (!sizeof(objlist)) return; printf("\n"); exec("ar", "rvs", library, "o/*.o"); exec("rm", "o/*.o"); printf("\n"); #endif } /* S T D C P P . I M */ void std_cpp(string library) { list cfiles; cfiles = file_list(sources, library); // make list of all cpp-files c_compile(cfiles); // compile cpp-files } /* C P P M A K E . C CPP files are processed by stdmake. Arguments of CPPMAKE: cpp_make( string mainfile, : name of the main .cpp file, or "" for library maintenance string library, : name of the local library to use/create (without lib prefix or .a/.so suffix (E.g., use `main' for `libmain.a') string exe, : (path) name of the exe file to create ) Both mainfile and library MUST be in the current directory */ void cpp_make(string mainfile, string library, string exe) { int index; if (nClasses) ofiles += " */o/*.o"; // set ofiles for no LIBRARY use // make library name #ifdef BUILD_LIBRARY if (!so_lib) libxxx = chdir(".") + "lib" + library + ".a"; #endif // first process all classes for (index = 0; index < nClasses; index++) { current = element(index, classes); // next class to process chdir(current); // change to directory current = "subdir " + current; std_cpp(libxxx); // compile all files chdir(cwd); // go back to parent dir } current = "auxiliary " + sources + " files"; std_cpp(libxxx); // compile all files in current dir #ifdef BUILD_LIBRARY if (!so_lib) { // prefix class-number for .o files for (index = 0; index < nClasses; index++) { current = element(index, classes); // determine class name chdir( current); // chdir to a class directory. prefix_class((string)index); updatelib(libxxx); chdir(cwd); // go back to parent dir } current = ""; // no class anymore updatelib(libxxx); // update lib in current dir } else { link_solib(library); // separate processing for so-lib return; } #endif if (mainfile != "") // mainfile -> do link { link(library, exe); printf ( "\nProgram construction completed.\n" "\n" ); } } /* S E T L I B S . I M */ void setlibs() { #ifdef LIBS int n, index; list cut; cut = strtok(LIBS, " "); // cut op libraries n = sizeof(cut); for (index = 0; index < n; index++) libs += " -l" + element(index, cut); #ifdef GRAMBUILD libs += " -lfl"; #endif cut = strtok(LIBPATH, " "); // cut up the paths n = sizeof(cut); for (index = 0; index < n; index++) libpath += " -L" + element(index, cut); #endif } void main() { initialize(); setlibs(); #ifdef BUILD_PROGRAM cpp_make ( "driver.cc", // program source "driver", // static program library "driver" // binary program ); #else cpp_make ( "", "driver", // static- or so-library "" ); #endif } bobcat-3.19.01/syslogstream/driver/driver.cc0000644000175000017500000000066112222576523017745 0ustar frankfrank/* driver.cc */ #include #include using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { Syslogbuf sbuf(argv[0]); // via a separate Syslogbuf ostream sls(0); sls.rdbuf(&sbuf); // SyslogStream sls(argv[0]); // via an explicit SyslogStream sls << SyslogStream::notice << "Hello world" << endl; } bobcat-3.19.01/syslogstream/debug.f0000644000175000017500000000014412223326067016076 0ustar frankfrankinline std::ostream &SyslogStream::debug(std::ostream &str) { return setPriority(str, DEBUG); } bobcat-3.19.01/syslogstream/maskvalue2.f0000644000175000017500000000022412223023055017050 0ustar frankfranktemplate inline int SyslogStream::maskValue(Priority p1, Priorities ...ps) { return ((1 << p1) | maskValue(ps ...)); } bobcat-3.19.01/syslogstream/setmask1.f0000644000175000017500000000015612223321623016534 0ustar frankfrankinline int SyslogStream::setMask(Priority p1, PriorityType upTo) { return setMask(maskValue(p1), upTo); } bobcat-3.19.01/syslogstream/close.f0000644000175000017500000000007612223321671016115 0ustar frankfrankinline void SyslogStream::close() { Syslogbuf::close(); } bobcat-3.19.01/syslogstream/err.f0000644000175000017500000000014012223325752015574 0ustar frankfrankinline std::ostream &SyslogStream::err(std::ostream &str) { return setPriority(str, ERR); } bobcat-3.19.01/syslogstream/notice.f0000644000175000017500000000014612223326015016264 0ustar frankfrankinline std::ostream &SyslogStream::notice(std::ostream &str) { return setPriority(str, NOTICE); } bobcat-3.19.01/syslogstream/defaultpriority.f0000644000175000017500000000014512223325440020231 0ustar frankfrankinline Priority SyslogStream::defaultPriority() const { return Syslogbuf::defaultPriority(); } bobcat-3.19.01/syslogstream/crit.f0000644000175000017500000000014212223325670015746 0ustar frankfrankinline std::ostream &SyslogStream::crit(std::ostream &str) { return setPriority(str, CRIT); } bobcat-3.19.01/syslogstream/setpriority2.cc0000644000175000017500000000033312222576523017632 0ustar frankfrank#include "syslogstream.ih" ostream &SyslogStream::setPriority(ostream &str, Priority value) { Syslogbuf *sb = dynamic_cast(str.rdbuf()); if (sb) sb->setPriority(value); return str; } bobcat-3.19.01/syslogstream/stop.cc0000644000175000017500000000106512222576523016143 0ustar frankfrank#include "syslogstream.ih" namespace { unordered_map priorityMap = { {"EMERG", FBB::EMERG}, {"ALERT", FBB::ALERT}, {"CRIT", FBB::CRIT}, {"ERR", FBB::ERR}, {"WARNING", FBB::WARNING}, {"NOTICE", FBB::NOTICE}, {"INFO", FBB::INFO}, {"DEBUG", FBB::DEBUG}, }; } Priority SyslogStream::stoP(std::string const &name, Priority priority) { auto iter = priorityMap.find(String::uc(name)); return iter == priorityMap.end() ? priority : iter->second; } bobcat-3.19.01/syslogstream/alert.f0000644000175000017500000000014412223325635016117 0ustar frankfrankinline std::ostream &SyslogStream::alert(std::ostream &str) { return setPriority(str, ALERT); } bobcat-3.19.01/syslogstream/stof.cc0000644000175000017500000000165112222576523016132 0ustar frankfrank#include "syslogstream.ih" namespace { unordered_map facilityMap = { {"AUTHPRIV", FBB::AUTHPRIV}, {"CRON", FBB::CRON}, {"DAEMON", FBB::DAEMON}, {"KERN", FBB::KERN}, {"LOCAL0", FBB::LOCAL0}, {"LOCAL1", FBB::LOCAL1}, {"LOCAL2", FBB::LOCAL2}, {"LOCAL3", FBB::LOCAL3}, {"LOCAL4", FBB::LOCAL4}, {"LOCAL5", FBB::LOCAL5}, {"LOCAL6", FBB::LOCAL6}, {"LOCAL7", FBB::LOCAL7}, {"LPR", FBB::LPR}, {"MAIL", FBB::MAIL}, {"NEWS", FBB::NEWS}, {"USER", FBB::USER}, {"UUCP", FBB::UUCP}, }; } Facility SyslogStream::stoF(std::string const &name, Facility facility) { auto iter = facilityMap.find(String::uc(name)); return iter == facilityMap.end() ? facility : iter->second; } bobcat-3.19.01/syslogstream/info.f0000644000175000017500000000014212223326041015731 0ustar frankfrankinline std::ostream &SyslogStream::info(std::ostream &str) { return setPriority(str, INFO); } bobcat-3.19.01/table/0000755000175000017500000000000012257325714013202 5ustar frankfrankbobcat-3.19.01/table/opinsert1.f0000644000175000017500000000013512223327147015267 0ustar frankfrankinline Table &operator<<(Table &tab, Align const &align) { return tab.setAlign(align); } bobcat-3.19.01/table/pushback.f0000644000175000017500000000016312223326726015146 0ustar frankfrankinline void Table::push_back(Element const &element) { d_tabulated = false; d_string.push_back(element); } bobcat-3.19.01/table/table.ih0000644000175000017500000000015212222576534014611 0ustar frankfrank#include "table" #include #include using namespace std; using namespace FBB; bobcat-3.19.01/table/def2.f0000644000175000017500000000007412223327401014156 0ustar frankfrankinline Table &def(Table &table) { return table.def(); } bobcat-3.19.01/table/fill.f0000644000175000017500000000032012223327620014261 0ustar frankfranktemplate void Table::fill(Iter it, Iter end) { TableBase::clear(); while (it != end) { std::ostringstream str; str << *it++; push_back(str.str()); } } bobcat-3.19.01/table/table0.cc0000644000175000017500000000022412222576534014656 0ustar frankfrank#include "table.ih" Table::Table(size_t nColumns, FillDirection direction, WidthType widthType) : TableBase(nColumns, direction, widthType) {} bobcat-3.19.01/table/table0000644000175000017500000000461412223327777014225 0ustar frankfrank#ifndef INCLUDED_BOBCAT_TABLE_ #define INCLUDED_BOBCAT_TABLE_ #include #include namespace FBB { class Table: public TableBase, public std::ostringstream { template friend Table &operator<<(Table &table, Type const &ref); public: typedef std::string value_type; // for C++-0x typedef Element const &const_reference; // required for push_back() Table(size_t nColumns, FillDirection direction, // 0 WidthType widthType = COLUMNWIDTH); Table(TableSupport &tableSupport, // 1 size_t nColumns, FillDirection direction, WidthType widthType = COLUMNWIDTH); Table(Table const &other) = delete; Table &operator=(Table const &other) = delete; Table &append(std::string const &str, char const *sep = " \t", bool addEmpty = false); template void fill(InputIterator begin, InputIterator end); // .f void push_back(Element const &element); // add an element to .f // the table, using the // default alignment. Table &setAlign(Align const &align); // set an alignment .f Table &def(); // fillup an incomplete table .f // automatically at insertions using TableBase::clear; void clearStr(); // clear the ostringstream part .f private: Table &flush(); // insert the text currently // inserted into the Table object // as ostringstream into the table }; #include "clearstr.f" #include "def1.f" #include "fill.f" #include "pushback.f" #include "setalign.f" // Free Functions // Insert column or element alignments #include "opinsert1.f" // Table << Align #include "def2.f" // Table &def(Table &def) // For def #include "opinsert2.f" // Table << Table &(*fun)(Table &) // Insert any other insertable type into a Table #include "opinsert3.f" // Table << Type const & } // FBB #endif bobcat-3.19.01/table/def1.f0000644000175000017500000000010712223327232014154 0ustar frankfrankinline Table &Table::def() { TableBase::def(); return *this; } bobcat-3.19.01/table/driver/0000755000175000017500000000000012222576534014475 5ustar frankfrankbobcat-3.19.01/table/driver/build0000755000175000017500000000010112222576534015512 0ustar frankfrank#!/bin/bash g++ -O2 --std=c++0x -o driver driver.cc -lbobcat -s bobcat-3.19.01/table/driver/driver.cc0000644000175000017500000000163312222576534016302 0ustar frankfrank#include #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) { TableLines tablelines; // width/separators of cols 0, 1 and 2 tablelines << 0 << " | " << " | "; // hline over cols 1 and 2 of row 1 tablelines << TableLines::HLine(1, 1, 3); Table tab(tablelines, 3, Table::ROWWISE, Table::EQUALWIDTH); // or: Table tab(tablelines, 3, Table::ROWWISE); tab << Align(0, std::left); // set column non-default alignment tab.fill(argv + 1, argv + argc);// fill range of values cout << tab << '\n'; // complete the table and insert tab << "hello" << "" << "wo"; // add additional elements. if (tab.nRows() > 2) tab << Align(2, 2, center); // set the layout of a specific element cout << tab << '\n'; } bobcat-3.19.01/table/clearstr.f0000644000175000017500000000010312223327570015155 0ustar frankfrankinline void Table::clearStr() { std::ostringstream::clear(); } bobcat-3.19.01/table/append.cc0000644000175000017500000000044512222576534014763 0ustar frankfrank#include "table.ih" Table &Table::append(string const &str, char const *sep, bool addEmpty) { if (sep == 0) sep = " \t"; vector words; String::split(&words, str, sep, addEmpty); copy(words.begin(), words.end(), back_inserter(*this)); return *this; } bobcat-3.19.01/table/flush.cc0000644000175000017500000000014512222576534014632 0ustar frankfrank#include "table.ih" Table &Table::flush() { push_back(str()); str(""); return *this; } bobcat-3.19.01/table/table1.cc0000644000175000017500000000032012222576534014654 0ustar frankfrank#include "table.ih" Table::Table(TableSupport &tableSupport, size_t nColumns, FillDirection direction, WidthType widthType) : TableBase(tableSupport, nColumns, direction, widthType) {} bobcat-3.19.01/table/opinsert2.f0000644000175000017500000000013512223327477015276 0ustar frankfrankinline Table &operator<<(Table &table, Table &(*fun)(Table &)) { return (*fun)(table); } bobcat-3.19.01/table/opinsert3.f0000644000175000017500000000032612223327754015277 0ustar frankfranktemplate // Insert any other insertable type into a Table Table &operator<<(Table &table, Type const &ref) { reinterpret_cast(table) << ref; return table.flush(); } bobcat-3.19.01/table/setalign.f0000644000175000017500000000015012223326755015152 0ustar frankfrankinline Table &Table::setAlign(Align const &align) { TableBase::setAlign(align); return *this; } bobcat-3.19.01/tablebase/0000755000175000017500000000000012257325714014035 5ustar frankfrankbobcat-3.19.01/tablebase/opinsert1.f0000644000175000017500000000014712223330547016123 0ustar frankfrankinline std::ostream &operator<<(std::ostream &str, TableBase &table) { return table.insert(str); } bobcat-3.19.01/tablebase/tablebase1.cc0000644000175000017500000000067112222576524016352 0ustar frankfrank#include "tablebase.ih" TableBase::TableBase(TableSupport &tableSupport, size_t nColumns, FillDirection direction, WidthType widthType) : d_tabulated(false), d_nRows(0), d_nColumns(nColumns), d_widthType(widthType), d_align(nColumns), d_ptr(0), d_tableSupport(tableSupport), d_indexFun(direction == ROWWISE ? &TableBase::hIndex : &TableBase::vIndex) {} bobcat-3.19.01/tablebase/element1.f0000644000175000017500000000025512223330453015705 0ustar frankfrankinline TableBase::Element::Element(std::string text, std::ios_base &(*manip)(std::ios_base &)) : d_text(text), d_manip(manip) {} bobcat-3.19.01/tablebase/tablebase0000644000175000017500000000603512223332740015674 0ustar frankfrank#ifndef INCLUDED_BOBCAT_TABLEBASE_ #define INCLUDED_BOBCAT_TABLEBASE_ #include #include #include #include #include namespace FBB { class TableBase { friend std::ostream &operator<<(std::ostream &str, TableBase &table); public: enum FillDirection { ROWWISE, COLUMNWISE }; enum WidthType { COLUMNWIDTH, EQUALWIDTH, }; void clear(); // clear the table-elements .f size_t nRows() const; // Number of rows currently .f // in the table (following def) protected: struct Element { std::string d_text; std::ios_base &(*d_manip)(std::ios_base &); Element(std::string text = "", // .f std::ios_base &(*manip)(std::ios_base &) = 0); size_t length() const; // .f }; bool d_tabulated; size_t d_nRows; size_t d_nColumns; WidthType d_widthType; std::vector d_align; std::vector d_string; // table contents TableSupport *d_ptr; TableSupport &d_tableSupport; Element &(TableBase::*d_indexFun)(size_t row, size_t col); TableBase(size_t nColumns, FillDirection direction, WidthType widthType); TableBase(TableSupport &tableSupport, // 1 size_t nColumns, FillDirection direction, WidthType widthType); ~TableBase(); void setAlign(Align const &align); // set an alignment void def(); // fillup an incomplete table // automatically called at // insertions into ostreams size_t columnWidth(size_t col) const; // .f Manipulator columnManip(size_t col) const; // .f Element &hIndex(size_t row, size_t col); // .f Element &vIndex(size_t row, size_t col); // .f private: std::ostream &insert(std::ostream &ostr); // returns element at particular location Element &elementAt(size_t row, size_t col); // .f }; #include "clear.f" #include "columnmanip.f" #include "columnwidth.f" #include "hindex.f" #include "nrows.f" #include "vindex.f" // Element members #include "element1.f" #include "length.f" // Free Functions // display the table #include "opinsert1.f" // ostream << TableBase } // FBB #endif bobcat-3.19.01/tablebase/destructor.cc0000644000175000017500000000010712222576524016537 0ustar frankfrank#include "tablebase.ih" TableBase::~TableBase() { delete d_ptr; } bobcat-3.19.01/tablebase/def.cc0000644000175000017500000000232312222576524015101 0ustar frankfrank#include "tablebase.ih" void TableBase::def() { if (d_tabulated || !d_string.size()) // no elements or already return; // tabulated then do nothing d_nRows = (d_string.size() + d_nColumns - 1) / d_nColumns; d_string.resize(d_nRows * d_nColumns); // enforce complete table // determine max width per column, // max column width, and alignment size_t maxWidth = 0; for (size_t col = 0; col < d_nColumns; ++col) { size_t maxColWidth = 0; for (size_t row = 0; row < d_nRows; ++row) { Element &element = elementAt(row, col); size_t len = element.length(); if (maxColWidth < len) maxColWidth = len; } d_align[col].setWidth(maxColWidth); // max. width so far. if (d_widthType == EQUALWIDTH && maxWidth < maxColWidth) maxWidth = maxColWidth; } if (d_widthType == EQUALWIDTH) { for (size_t col = 0; col < d_nColumns; ++col) d_align[col].setWidth(maxWidth); } d_tabulated = true; } bobcat-3.19.01/tablebase/tablebase.ih0000644000175000017500000000015412223331445016270 0ustar frankfrank#include "tablebase" #include using namespace std; using namespace FBB; #include "elementat.f" bobcat-3.19.01/tablebase/insert.cc0000644000175000017500000000232412222576524015650 0ustar frankfrank#include "tablebase.ih" ostream &TableBase::insert(ostream &ostr) { def(); if (!d_nRows) return ostr; d_tableSupport.setParam(ostr, d_nRows, d_nColumns, d_align); for (size_t row = 0; row < d_nRows; ++row) { d_tableSupport.hline(row); for (size_t col = 0; col < d_nColumns; ++col) { size_t colwidth = columnWidth(col); d_tableSupport.vline(col); Element &element = elementAt(row, col); Manipulator manip = element.d_manip; if (!manip) manip = columnManip(col); if (manip != FBB::center) ostr << manip << setw(colwidth) << element.d_text; else { int available = colwidth - element.length(); if (available < 0) available = 0; if (size_t skip = available >> 1) ostr << setw(skip) << " "; ostr << element.d_text; if (size_t skip = available - (available >> 1)) ostr << setw(skip) << " "; } } d_tableSupport.vline(); } d_tableSupport.hline(); return ostr; } bobcat-3.19.01/tablebase/nrows.f0000644000175000017500000000007712223330367015351 0ustar frankfrankinline size_t TableBase::nRows() const { return d_nRows; } bobcat-3.19.01/tablebase/columnwidth.f0000644000175000017500000000012412223331026016520 0ustar frankfrankinline size_t TableBase::columnWidth(size_t col) const { return d_align[col]; } bobcat-3.19.01/tablebase/setalign.cc0000644000175000017500000000040612222576524016151 0ustar frankfrank#include "tablebase.ih" void TableBase::setAlign(Align const &align) { d_tabulated = false; if (align.hasRow()) elementAt(align.row(), align.col()).d_manip = align.manip(); else d_align[align.col()].setManip(align.manip()); } bobcat-3.19.01/tablebase/hindex.f0000644000175000017500000000016612223331167015456 0ustar frankfrankinline TableBase::Element &TableBase::hIndex(size_t row, size_t col) { return d_string[row * d_nColumns + col]; } bobcat-3.19.01/tablebase/length.f0000644000175000017500000000012112223330665015451 0ustar frankfrankinline size_t TableBase::Element::length() const { return d_text.length(); } bobcat-3.19.01/tablebase/clear.f0000644000175000017500000000012212223330331015245 0ustar frankfrankinline void TableBase::clear() { d_tabulated = false; d_string.clear(); } bobcat-3.19.01/tablebase/elementat.f0000644000175000017500000000016612223331315016150 0ustar frankfrankinline TableBase::Element &TableBase::elementAt(size_t row, size_t col) { return (this->*d_indexFun)(row, col); } bobcat-3.19.01/tablebase/vindex.f0000644000175000017500000000016312223331204015461 0ustar frankfrankinline TableBase::Element &TableBase::vIndex(size_t row, size_t col) { return d_string[col * d_nRows + row]; } bobcat-3.19.01/tablebase/tablebase0.cc0000644000175000017500000000072412222576524016350 0ustar frankfrank#include "tablebase.ih" TableBase::TableBase(size_t nColumns, FillDirection direction, WidthType widthType) : d_tabulated(false), d_nRows(0), d_nColumns(nColumns), d_widthType(widthType), d_align(nColumns), d_ptr(new TableSupport()), d_tableSupport(*d_ptr), d_indexFun(direction == ROWWISE ? &TableBase::hIndex : &TableBase::vIndex) {} bobcat-3.19.01/tablebase/columnmanip.f0000644000175000017500000000022512223331052016506 0ustar frankfrankinline Manipulator TableBase::columnManip(size_t col) const { Manipulator manip = d_align[col].manip(); return manip ? manip : std::right; } bobcat-3.19.01/tablebuf/0000755000175000017500000000000012257325714013677 5ustar frankfrankbobcat-3.19.01/tablebuf/tablebuf0000644000175000017500000000362712223332634015406 0ustar frankfrank#ifndef INCLUDED_BOBCAT_TABLEBUF_ #define INCLUDED_BOBCAT_TABLEBUF_ #include #include namespace FBB { class TableBuf: public TableBase, public std::streambuf { friend std::ostream &operator<<(std::ostream &str, // 1.f TableBuf &table); friend std::ostream &fs(std::ostream &out); friend std::ostream &rs(std::ostream &out); int d_fs; int d_rs; std::string d_str; bool d_buffered; bool d_insertEmptyRow; public: TableBuf(size_t nColumns, FillDirection direction, // 0 WidthType widthType = COLUMNWIDTH); TableBuf(TableSupport &tableSupport, // 1 size_t nColumns, FillDirection direction, WidthType widthType = COLUMNWIDTH); TableBuf &def(); // fillup an incomplete table 1.f TableBuf &setAlign(Align const &align); // set alignment .f void setFieldSeparator(); // 1.f void setFieldSeparator(char fs); // 2.f void setRowSeparator(); // 1.f void setRowSeparator(char rs); // 2.f protected: virtual int pSync(); private: virtual int sync(); virtual int overflow(int ch); void nextField(); void endRow(); }; std::ostream &fs(std::ostream &out); std::ostream &rs(std::ostream &out); #include "setalign.f" #include "setfieldseparator1.f" #include "setfieldseparator2.f" #include "setrowseparator1.f" #include "setrowseparator2.f" // Free Members #include "def2.f" // TableBuf &def(TableBuf &table) // Insert column or element alignments #include "opinsert2.f" // TableBuf << Align } // FBB #endif bobcat-3.19.01/tablebuf/endrow.cc0000644000175000017500000000034512222576523015504 0ustar frankfrank#include "tablebuf.ih" void TableBuf::endRow() { d_string.resize( ( (d_string.size() + d_nColumns - 1) / d_nColumns + d_insertEmptyRow ) * d_nColumns); d_insertEmptyRow = true; } bobcat-3.19.01/tablebuf/tablebuf1.cc0000644000175000017500000000045212222576523016052 0ustar frankfrank#include "tablebuf.ih" TableBuf::TableBuf(TableSupport &tableSupport, size_t nColumns, FillDirection direction, WidthType widthType) : TableBase(tableSupport, nColumns, direction, widthType), d_fs('\b'), d_rs('\n'), d_buffered(false), d_insertEmptyRow(false) {} bobcat-3.19.01/tablebuf/tablebuf.ih0000644000175000017500000000007712222576523016007 0ustar frankfrank#include "tablebuf" using namespace std; using namespace FBB; bobcat-3.19.01/tablebuf/operatorinsert.cc0000644000175000017500000000031712222576523017265 0ustar frankfrank#include "tablebuf.ih" // displays the table std::ostream &FBB::operator<<(std::ostream &out, TableBuf &table) { table.sync(); TableBase &tb = table; return out << tb; } bobcat-3.19.01/tablebuf/tablebuf0.cc0000644000175000017500000000045212222576523016051 0ustar frankfrank#include "tablebuf.ih" TableBuf::TableBuf(size_t nColumns, FillDirection direction, WidthType widthType) : TableBase(nColumns, direction, widthType), d_fs('\b'), d_rs('\n'), d_buffered(false), d_insertEmptyRow(false) {} bobcat-3.19.01/tablebuf/def2.f0000644000175000017500000000010212223332546014651 0ustar frankfrankinline TableBuf &def(TableBuf &table) { return table.def(); } bobcat-3.19.01/tablebuf/setfieldseparator1.f0000644000175000017500000000007512223331754017643 0ustar frankfrankinline void TableBuf::setFieldSeparator() { d_fs = -1; } bobcat-3.19.01/tablebuf/nextfield.cc0000644000175000017500000000023312222576523016164 0ustar frankfrank#include "tablebuf.ih" void TableBuf::nextField() { d_tabulated = false; d_string.push_back(d_str); d_str.erase(); d_buffered = false; } bobcat-3.19.01/tablebuf/fs.cc0000644000175000017500000000027212222576523014615 0ustar frankfrank#include "tablebuf.ih" namespace FBB { std::ostream &fs(std::ostream &out) { TableBuf &tb = dynamic_cast(*out.rdbuf()); tb.overflow(tb.d_fs); return out; } } bobcat-3.19.01/tablebuf/def1.f0000644000175000017500000000011512223332531014646 0ustar frankfrankinline TableBuf &TableBuf::def() { TableBase::def(); return *this; } bobcat-3.19.01/tablebuf/driver/0000755000175000017500000000000012222576523015170 5ustar frankfrankbobcat-3.19.01/tablebuf/driver/build0000755000175000017500000000024612222576523016217 0ustar frankfrank#!/bin/bash #g++ -O2 -Wall --std=c++0x -o driver driver.cc -lbobcat -s g++ -I../../tmp -Wall -O2 --std=c++0x -o driver driver.cc \ -L../../tmp/lib -lbobcat -s bobcat-3.19.01/tablebuf/driver/driver.cc0000644000175000017500000000122112222576523016766 0ustar frankfrank#include #include #include #include #include #include #include using namespace std; using namespace FBB; int main() { TableLines tablelines; tablelines << 0; // set separator widths for (size_t sep = 0; sep != 8; ++sep) tablelines << 3; TableBuf tab(tablelines, 8, TableBuf::ROWWISE); ostream out(&tab); copy(istream_iterator(cin), istream_iterator(), ostream_iterator(out, "\b")); cout << tab << '\n'; // complete the table and insert } bobcat-3.19.01/tablebuf/setrowseparator1.f0000644000175000017500000000007312223332067017363 0ustar frankfrankinline void TableBuf::setRowSeparator() { d_rs = -1; } bobcat-3.19.01/tablebuf/overflow.cc0000644000175000017500000000050312222576523016045 0ustar frankfrank#include "tablebuf.ih" int TableBuf::overflow(int ch) { if (ch == d_fs) nextField(); else if (ch == d_rs) { nextField(); endRow(); } else { d_str += static_cast(ch); d_buffered = true; d_insertEmptyRow = false; } return ch; } bobcat-3.19.01/tablebuf/setrowseparator2.f0000644000175000017500000000010212223332103017344 0ustar frankfrankinline void TableBuf::setRowSeparator(char rs) { d_rs = rs; } bobcat-3.19.01/tablebuf/psync.cc0000644000175000017500000000015212222576523015336 0ustar frankfrank#include "tablebuf.ih" int TableBuf::pSync() { if (d_buffered) nextField(); return 0; } bobcat-3.19.01/tablebuf/opinsert2.f0000644000175000017500000000014312223332263015757 0ustar frankfrankinline TableBuf &operator<<(TableBuf &tab, Align const &align) { return tab.setAlign(align); } bobcat-3.19.01/tablebuf/rs.cc0000644000175000017500000000027212222576523014631 0ustar frankfrank#include "tablebuf.ih" namespace FBB { std::ostream &rs(std::ostream &out) { TableBuf &tb = dynamic_cast(*out.rdbuf()); tb.overflow(tb.d_rs); return out; } } bobcat-3.19.01/tablebuf/sync.cc0000644000175000017500000000010512222576523015154 0ustar frankfrank#include "tablebuf.ih" int TableBuf::sync() { return pSync(); } bobcat-3.19.01/tablebuf/setfieldseparator2.f0000644000175000017500000000010412223332002017620 0ustar frankfrankinline void TableBuf::setFieldSeparator(char fs) { d_fs = fs; } bobcat-3.19.01/tablebuf/setalign.f0000644000175000017500000000015612223332146015644 0ustar frankfrankinline TableBuf &TableBuf::setAlign(Align const &align) { TableBase::setAlign(align); return *this; } bobcat-3.19.01/tablelines/0000755000175000017500000000000012257325714014235 5ustar frankfrankbobcat-3.19.01/tablelines/opassign.f0000644000175000017500000000015512223335555016225 0ustar frankfrankinline TableLines &TableLines::operator=(TableLines &&tmp) { *this = std::move(tmp); return *this; } bobcat-3.19.01/tablelines/tablelines1.f0000644000175000017500000000012612223335461016577 0ustar frankfrankinline TableLines::TableLines(TableLines &&tmp) : TableSupport(std::move(tmp)) {} bobcat-3.19.01/tablelines/outline.cc0000644000175000017500000000127712222576533016231 0ustar frankfrank#include "tablelines.ih" void TableLines::outLine(Field const &field, ostream &out) { if (field.width == 0) return; if (field.type == SKIP) out << setw(field.width) << " "; else if ((field.type & (LEFT_FULL | USE | RIGHT_FULL))) out << setfill('-') << setw(field.width) << "-" << setfill(' '); else if (field.type & LEFT_MID) { out << setw(field.width / 2) << " " << setfill('-') << setw(field.width - field.width / 2) << "-" << setfill(' '); } else { out << setfill('-') << setw(field.width - field.width / 2) << "-" << setfill(' ') << setw(field.width / 2) << " "; } } bobcat-3.19.01/tablelines/tablelines.ih0000644000175000017500000000020212222576533016672 0ustar frankfrank#include "tablelines" #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/tablelines/tablelines0000644000175000017500000000105112223335567016277 0ustar frankfrank#ifndef INCLUDED_TABLELINES_ #define INCLUDED_TABLELINES_ #include #include namespace FBB { class TableLines: public TableSupport { public: TableLines() = default; TableLines(TableLines &&tmp); // 1.f TableLines &operator=(TableLines &&tmp); // opassign.f private: virtual void v_hline(size_t row) const; static void outLine(Field const &field, std::ostream &out); }; #include "tablelines1.f" #include "opassign.f" } // FBB #endif bobcat-3.19.01/tablelines/vhline.cc0000644000175000017500000000066712222576533016041 0ustar frankfrank#include "tablelines.ih" void TableLines::v_hline(size_t row) const { if (row == 0 || row == nRows()) out() << setfill('-') << setw(width()) << "-" << setfill(' '); else { const_iterator iter = begin(row); const_iterator beyond = end(row); if (iter == beyond) return; for (auto &field: ranger(iter, beyond)) outLine(field, out()); } out() << '\n'; } bobcat-3.19.01/tablesupport/0000755000175000017500000000000012257325714014637 5ustar frankfrankbobcat-3.19.01/tablesupport/sepwidth.f0000644000175000017500000000016412223550765016635 0ustar frankfrankinline size_t TableSupport::sepWidth(size_t col) const { return col < d_sep.size() ? d_sep[col].length() : 0; } bobcat-3.19.01/tablesupport/setparam.cc0000644000175000017500000000077212222576524016767 0ustar frankfrank#include "tablesupport.ih" void TableSupport::setParam(std::ostream &ostr, size_t rows, size_t nColumns, std::vector const &align) { d_streamPtr = &ostr; d_nRows = rows; d_nColumns = nColumns; d_align = &align; d_tableWidth = accumulate(align.begin(), align.end(), 0); for (auto &elements: d_elements) elements.second.resize(rightSeparator(d_nColumns) + 1); for (auto &src: d_sep) d_tableWidth += src.length(); } bobcat-3.19.01/tablesupport/destructor.cc0000644000175000017500000000007512222576524017345 0ustar frankfrank#include "tablesupport.ih" TableSupport::~TableSupport() {} bobcat-3.19.01/tablesupport/opbitor.f0000644000175000017500000000041212223550765016460 0ustar frankfrankinline TableSupport::ColumnType operator|(TableSupport::ColumnType lhs, TableSupport::ColumnType rhs) { return static_cast( static_cast(lhs) | static_cast(rhs)); } bobcat-3.19.01/tablesupport/tablesupport0000644000175000017500000001535112223613536017306 0ustar frankfrank#ifndef INCLUDED_BOBCAT_TABLESUPPORT_ #define INCLUDED_BOBCAT_TABLESUPPORT_ #include #include #include #include #include namespace FBB { class TableSupport { public: struct Field { size_t width; // width of a field size_t type; // handlingtype (ColumnType) }; enum ColumnType { SKIP = 0, USE = 1 << 0, LEFT_FULL = 1 << 1, RIGHT_FULL = 1 << 2, LEFT_MID = 1 << 3, RIGHT_MID = 1 << 4 }; // define the columns to provide with a (partial) hline struct HLine { size_t d_row; size_t d_begin; size_t d_end; size_t d_type; HLine(size_t row, size_t begin, size_t end); HLine(ColumnType margins, size_t row, size_t begin, size_t end); }; class const_iterator: public std::iterator { TableSupport const &d_support; // iterators to vectors in d_elements. The elements of the // vectors contain the types of the column (SKIP, USE, etc) // to determine the width of an element call // separator.width(iterator) std::vector const *d_vector; std::vector::const_iterator d_iter; mutable Field d_field; static std::vector s_empty; public: const_iterator(TableSupport const &support, size_t row, bool begin); const_iterator &operator++(); // .f bool operator==(const_iterator const &other) const; // .f bool operator!=(const_iterator const &other) const; // .f Field const &operator*() const; // .f Field const *operator->() const; }; private: std::ostream *d_streamPtr; size_t d_nRows; // # of rows (defined after def()) size_t d_nColumns; // # of cols std::vector const *d_align; // pointer to alignment info, // passed to this by setParam, // (used by Table/TableBuf) size_t d_tableWidth; // total table width std::vector d_sep; // a vector of separators. 0: // before the leftmost col. // Element types per row per // column, wrt hlines typedef std::unordered_map> UMsizeVector; typedef UMsizeVector::value_type UMValue; typedef UMsizeVector::const_iterator UMIter; UMsizeVector d_elements; public: TableSupport(); TableSupport(TableSupport &&tmp); TableSupport &operator=(TableSupport &&tmp); virtual ~TableSupport(); // empty void setParam(std::ostream &ostr, size_t rows, size_t nColumns, std::vector const &align); void hline() const; // called after the last data row 1.f // called by Table/TableBuf for each row (0: before 1st data row) void hline(size_t row) const; // 2.f // same for columns void vline() const; // 1.f void vline(size_t col) const; // 2.f size_t width() const; // total width of the table .f protected: const_iterator begin(size_t row) const; // .f const_iterator end(size_t row) const; // .f size_t colWidth(size_t col) const; // width of a column and: .f size_t sepWidth(size_t col) const; // of a separator .f // (0: leftmost) size_t nColumns() const; // number of columns .f size_t nRows() const; // number of rows .f std::ostream &out() const; // stream to insert into .f // the table // col. alignmnts (not separators) std::vector const &align() const; // .f std::vector const &sep() const; // separators .f private: // called for each row (0: before 1st data row) virtual void v_hline(size_t row) const; virtual void v_hline() const; // called after the last data row // same for columns virtual void v_vline(size_t col) const; virtual void v_vline() const; size_t width(size_t idx) const; // return indices in d_elements of left separator element, etc. static size_t leftSeparator(size_t column); // .f static size_t element(size_t column); // .f static size_t rightSeparator(size_t column); // .f static void leftType(size_t *target, size_t type); // .f static void rightType(size_t *target, size_t type); // .f friend class const_iterator; friend TableSupport &operator<<(TableSupport &support, size_t); friend TableSupport &operator<<(TableSupport &support, std::string const &sep); friend TableSupport &operator<<(TableSupport &support, HLine const &hline); }; #include "align.f" #include "begin.f" #include "colwidth.f" #include "end.f" #include "hline1.f" #include "hline2.f" #include "ncolumns.f" #include "nrows.f" #include "opeq.f" #include "opinc.f" #include "opneq.f" #include "opstar.f" #include "out.f" #include "sep.f" #include "sepwidth.f" #include "vline1.f" #include "vline2.f" #include "width.f" // Free Functions #include "opbitor.f" // ColumnType | ColumnType TableSupport &operator<<(TableSupport &support, size_t); TableSupport &operator<<(TableSupport &support, std::string const &sep); TableSupport &operator<<(TableSupport &support, TableSupport::HLine const &hline); } // FBB #endif bobcat-3.19.01/tablesupport/out.f0000644000175000017500000000011412223550765015610 0ustar frankfrankinline std::ostream &TableSupport::out() const { return *d_streamPtr; } bobcat-3.19.01/tablesupport/colwidth.f0000644000175000017500000000017112223550765016621 0ustar frankfrankinline size_t TableSupport::colWidth(size_t col) const { return col < d_align->size() ? (*d_align)[col].col() : 0; } bobcat-3.19.01/tablesupport/nrows.f0000644000175000017500000000010212223550765016146 0ustar frankfrankinline size_t TableSupport::nRows() const { return d_nRows; } bobcat-3.19.01/tablesupport/operatorinhline.cc0000644000175000017500000000145612222576524020355 0ustar frankfrank#include "tablesupport.ih" TableSupport &FBB::operator<<(TableSupport &support, TableSupport::HLine const &hline) { if (hline.d_begin >= hline.d_end) return support; vector &elements = support.d_elements[hline.d_row]; size_t nCols = max(hline.d_end, support.d_nColumns); elements.resize(1 + TableSupport::rightSeparator(nCols)); TableSupport::leftType( &elements[TableSupport::leftSeparator(hline.d_begin)], hline.d_type); int end = TableSupport::leftSeparator(hline.d_end); TableSupport::rightType(&elements[end], hline.d_type); for ( int idx = TableSupport::element(hline.d_begin); idx != end; ++idx ) elements[idx] = TableSupport::USE; return support; } bobcat-3.19.01/tablesupport/ncolumns.f0000644000175000017500000000011012223550765016633 0ustar frankfrankinline size_t TableSupport::nColumns() const { return d_nColumns; } bobcat-3.19.01/tablesupport/leftseparator.f0000644000175000017500000000012412223613363017647 0ustar frankfrankinline size_t TableSupport::leftSeparator(size_t column) { return column * 2; } bobcat-3.19.01/tablesupport/sep.f0000644000175000017500000000012712223550765015574 0ustar frankfrankinline std::vector const &TableSupport::sep() const { return d_sep; } bobcat-3.19.01/tablesupport/operatorinstring.cc0000644000175000017500000000030012222576524020547 0ustar frankfrank#include "tablesupport.ih" TableSupport &FBB::operator<<(TableSupport &support, std::string const &sep) { support.d_sep.push_back(sep); --support.d_tableWidth; return support; } bobcat-3.19.01/tablesupport/hline1.f0000644000175000017500000000007312223550765016165 0ustar frankfrankinline void TableSupport::hline() const { v_hline(); } bobcat-3.19.01/tablesupport/opstar.f0000644000175000017500000000021412223550765016312 0ustar frankfrankinline TableSupport::Field const &TableSupport::const_iterator::operator*() const { return *operator->(); } bobcat-3.19.01/tablesupport/tablesupport2.cc0000644000175000017500000000043312222576524017753 0ustar frankfrank#include "tablesupport.ih" TableSupport::TableSupport(TableSupport &&tmp) : d_streamPtr(tmp.d_streamPtr), d_nRows(tmp.d_nRows), d_nColumns(tmp.d_nColumns), d_align(tmp.d_align), d_tableWidth( move(tmp.d_tableWidth) ), d_elements( move(tmp.d_elements) ) {} bobcat-3.19.01/tablesupport/element.f0000644000175000017500000000012212223613411016415 0ustar frankfrankinline size_t TableSupport::element(size_t column) { return column * 2 + 1; } bobcat-3.19.01/tablesupport/constiterator1.cc0000644000175000017500000000070712222576524020132 0ustar frankfrank#include "tablesupport.ih" TableSupport::const_iterator::const_iterator(TableSupport const &support, size_t row, bool begin) : d_support(support) { UMIter iter = support.d_elements.find(row); if (iter != support.d_elements.end()) { d_vector = &iter->second; d_iter = begin ? d_vector->begin() : d_vector->end(); } else { d_vector = &s_empty; d_iter = s_empty.end(); } } bobcat-3.19.01/tablesupport/begin.f0000644000175000017500000000021012223550765016062 0ustar frankfrankinline TableSupport::const_iterator TableSupport::begin(size_t row) const { const_iterator ret(*this, row, true); return ret; } bobcat-3.19.01/tablesupport/data.cc0000644000175000017500000000012312222576524016052 0ustar frankfrank#include "tablesupport.ih" vector TableSupport::const_iterator::s_empty; bobcat-3.19.01/tablesupport/vhline2.cc0000644000175000017500000000012712222576524016514 0ustar frankfrank#include "tablesupport.ih" void TableSupport::v_hline() const { hline(d_nRows); } bobcat-3.19.01/tablesupport/vvline0.cc0000644000175000017500000000020712222576524016527 0ustar frankfrank#include "tablesupport.ih" void TableSupport::v_vline(size_t col) const { if (col < d_sep.size()) out() << d_sep[col]; } bobcat-3.19.01/tablesupport/tablesupport1.cc0000644000175000017500000000023212222576524017747 0ustar frankfrank#include "tablesupport.ih" TableSupport::TableSupport() : d_streamPtr(0), d_nRows(0), d_nColumns(0), d_align(0), d_tableWidth(0) {} bobcat-3.19.01/tablesupport/width.cc0000644000175000017500000000024012222576524016260 0ustar frankfrank#include "tablesupport.ih" #include size_t TableSupport::width(size_t idx) const { return idx & 1 ? colWidth(idx >> 1) : sepWidth(idx >> 1); } bobcat-3.19.01/tablesupport/opeq.f0000644000175000017500000000022612223550765015751 0ustar frankfrankinline bool TableSupport::const_iterator::operator==( TableSupport::const_iterator const &other) const { return d_iter == other.d_iter; } bobcat-3.19.01/tablesupport/opneq.f0000644000175000017500000000022012223550765016121 0ustar frankfrankinline bool TableSupport::const_iterator::operator!=( TableSupport::const_iterator const &other) const { return not (*this == other); } bobcat-3.19.01/tablesupport/end.f0000644000175000017500000000020712223550765015552 0ustar frankfrankinline TableSupport::const_iterator TableSupport::end(size_t row) const { const_iterator ret(*this, row, false); return ret; } bobcat-3.19.01/tablesupport/vline2.f0000644000175000017500000000011012223550765016174 0ustar frankfrankinline void TableSupport::vline(size_t col) const { v_vline(col); } bobcat-3.19.01/tablesupport/hline1.cc0000644000175000017500000000025012222576524016322 0ustar frankfrank#include "tablesupport.ih" TableSupport::HLine::HLine(size_t row, size_t begin, size_t end) : d_row(row), d_begin(begin), d_end(end), d_type(SKIP) {} bobcat-3.19.01/tablesupport/vvline1.cc0000644000175000017500000000015612222576524016533 0ustar frankfrank#include "tablesupport.ih" void TableSupport::v_vline() const { vline(d_nColumns); out() << '\n'; } bobcat-3.19.01/tablesupport/righttype.f0000644000175000017500000000032212223613567017021 0ustar frankfrankinline void TableSupport::rightType(size_t *target, size_t type) { *target = *target != SKIP || (type & (USE | RIGHT_FULL)) ? USE : RIGHT_MID; } bobcat-3.19.01/tablesupport/hline0.cc0000644000175000017500000000052312222576524016324 0ustar frankfrank#include "tablesupport.ih" TableSupport::HLine::HLine(ColumnType margins, size_t row, size_t begin, size_t end) : d_row(row), d_begin(begin), d_end(end), d_type(margins) { if (d_type & LEFT_FULL) d_type &= ~LEFT_MID; if (d_type & RIGHT_FULL) d_type &= ~RIGHT_MID; } bobcat-3.19.01/tablesupport/align.f0000644000175000017500000000012612223550765016076 0ustar frankfrankinline std::vector const &TableSupport::align() const { return *d_align; } bobcat-3.19.01/tablesupport/width.f0000644000175000017500000000010712223550765016122 0ustar frankfrankinline size_t TableSupport::width() const { return d_tableWidth; } bobcat-3.19.01/tablesupport/operatorinsizet.cc0000644000175000017500000000031212222576524020402 0ustar frankfrank#include "tablesupport.ih" TableSupport &FBB::operator<<(TableSupport &support, size_t width) { support.d_sep.push_back(std::string(width, ' ')); --support.d_tableWidth; return support; } bobcat-3.19.01/tablesupport/vhline.cc0000644000175000017500000000011412222576524016426 0ustar frankfrank#include "tablesupport.ih" void TableSupport::v_hline(size_t row) const {} bobcat-3.19.01/tablesupport/rightseparator.f0000644000175000017500000000013112223613460020026 0ustar frankfrankinline size_t TableSupport::rightSeparator(size_t column) { return column * 2 + 2; } bobcat-3.19.01/tablesupport/hline2.f0000644000175000017500000000011012223550765016156 0ustar frankfrankinline void TableSupport::hline(size_t row) const { v_hline(row); } bobcat-3.19.01/tablesupport/operatorassign.cc0000644000175000017500000000020412222576524020201 0ustar frankfrank#include "tablesupport.ih" TableSupport &TableSupport::operator=(TableSupport &&tmp) { fswap(*this, tmp); return *this; } bobcat-3.19.01/tablesupport/opinc.f0000644000175000017500000000016512223550765016117 0ustar frankfrankinline TableSupport::const_iterator &TableSupport::const_iterator::operator++() { ++d_iter; return *this; } bobcat-3.19.01/tablesupport/vline1.f0000644000175000017500000000007312223550765016203 0ustar frankfrankinline void TableSupport::vline() const { v_vline(); } bobcat-3.19.01/tablesupport/lefttype.f0000644000175000017500000000031712223613522016631 0ustar frankfrankinline void TableSupport::leftType(size_t *target, size_t type) { *target = *target != SKIP || (type & (USE | LEFT_FULL)) ? USE : LEFT_MID; } bobcat-3.19.01/tablesupport/tablesupport.ih0000644000175000017500000000035412223613603017675 0ustar frankfrank#include "tablesupport" #include #include using namespace std; using namespace FBB; #include "leftseparator.f" #include "rightseparator.f" #include "element.f" #include "lefttype.f" #include "righttype.f" bobcat-3.19.01/tablesupport/operatorarrow.cc0000644000175000017500000000031712222576525020055 0ustar frankfrank#include "tablesupport.ih" TableSupport::Field const *TableSupport::const_iterator::operator->() const { d_field = Field { d_support.width(d_iter - d_vector->begin()), *d_iter }; return &d_field; } bobcat-3.19.01/tempstream/0000755000175000017500000000000012257325714014274 5ustar frankfrankbobcat-3.19.01/tempstream/destructor.cc0000644000175000017500000000013012222576530016767 0ustar frankfrank#include "tempstream.ih" TempStream::~TempStream() { unlink(d_fileName.c_str()); } bobcat-3.19.01/tempstream/tempstream0000644000175000017500000000064312223614030016364 0ustar frankfrank#ifndef INCLUDED_TEMPSTREAM_ #define INCLUDED_TEMPSTREAM_ #include #include namespace FBB { class TempStream: public std::fstream { std::string d_fileName; public: TempStream(std::string const &base = "/tmp/FBB::TempStream"); ~TempStream(); std::string const &fileName() const; // .f }; #include "filename.f" } // FBB #endif bobcat-3.19.01/tempstream/filename.f0000644000175000017500000000012212223614023016201 0ustar frankfrankinline std::string const &TempStream::fileName() const { return d_fileName; } bobcat-3.19.01/tempstream/driver/0000755000175000017500000000000012222576530015563 5ustar frankfrankbobcat-3.19.01/tempstream/driver/driver.cc0000644000175000017500000000043212222576530017364 0ustar frankfrank#include #include "../tempstream" using namespace std; using namespace FBB; int main() { TempStream ts("/tmp/demo"); ts << "Hello world\n"; ts.seekg(0); string line; getline(ts, line); cout << line << ", removed: " << ts.fileName() << '\n'; } bobcat-3.19.01/tempstream/tempstream.ih0000644000175000017500000000023212222576530016770 0ustar frankfrank#include "tempstream" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/tempstream/tempstream1.cc0000644000175000017500000000064012222576530017041 0ustar frankfrank#include "tempstream.ih" TempStream::TempStream(string const &base) { char *buf = new char[base.length() + 6 + 1]; strcpy(buf + base.length(), "XXXXXX"); base.copy(buf, string::npos); int fd = mkostemp(buf, O_RDWR); if (fd == -1) throw Exception() << "TempStream: " << errnodescr; d_fileName = buf; delete[] buf; ::close(fd); open(d_fileName, ios::out | ios::in); } bobcat-3.19.01/typetrait/0000755000175000017500000000000012222576536014142 5ustar frankfrankbobcat-3.19.01/typetrait/driver/0000755000175000017500000000000012222576536015435 5ustar frankfrankbobcat-3.19.01/typetrait/driver/build0000755000175000017500000000007312222576536016462 0ustar frankfrank#!/bin/bash g++ --std=c++0x -Wall -o driver driver.cc -s bobcat-3.19.01/typetrait/driver/driver.cc0000644000175000017500000000276112222576536017245 0ustar frankfrank#include #include #include "../typetrait" using namespace std; using namespace FBB; template void show(char const *name) { cout << "Type: " << name << boolalpha << ":\n" " " "is class: " << TypeTrait::isClass << ", " "is const: " << TypeTrait::isConst << ", " "is pointer: " << TypeTrait::isPointer << ", " "is r-ref: " << TypeTrait::isR_Ref << ", " "is ref: " << TypeTrait::isRef << '\n'; } int main() { TypeTrait::Plain int1 = 12; TypeTrait::Plain int2 = 12; TypeTrait::Plain int3 = 12; TypeTrait::Plain int4 = 12; TypeTrait::Plain int5 = 12; TypeTrait::Plain int6 = 12; show("int"); show("int *"); show("int const"); show("int const *"); show("int &"); show("int const &"); show("int &&"); show("int const &&"); show("std::string"); cout << "=======================\n"; cout << "string promotes char const *: " << LpromotesR::yes << '\n'; cout << "string promotes string " << LpromotesR::yes << '\n'; cout << "char const * promotes string " << LpromotesR::yes << '\n'; } bobcat-3.19.01/typetrait/typetrait0000644000175000017500000000645512222576536016124 0ustar frankfrank#ifndef INCLUDED_BOBCAT_TYPETRAIT_ #define INCLUDED_BOBCAT_TYPETRAIT_ #include namespace FBB { template class TypeTrait { template static double fun(void (ClassType::*)()); template static char fun(...); template struct Type { enum { isClass = sizeof(fun(0)) == sizeof(double) }; enum { isConst = false }; enum { isPointer = false }; enum { isR_Ref = false }; enum { isRef = false }; typedef U Plain; }; template struct Type { enum { isClass = sizeof(fun(0)) == sizeof(double) }; enum { isPointer = false }; enum { isConst = true }; enum { isRef = false }; enum { isR_Ref = false }; typedef U Plain; }; template struct Type { enum { isClass = false }; enum { isPointer = true }; enum { isConst = false }; enum { isRef = false }; enum { isR_Ref = false }; typedef U Plain; }; template struct Type { enum { isClass = false }; enum { isPointer = true }; enum { isConst = true }; enum { isRef = false }; enum { isR_Ref = false }; typedef U Plain; }; template struct Type { enum { isClass = sizeof(fun(0)) == sizeof(double) }; enum { isPointer = false }; enum { isConst = false }; enum { isRef = true }; enum { isR_Ref = false }; typedef U Plain; }; template struct Type { enum { isClass = sizeof(fun(0)) == sizeof(double) }; enum { isPointer = false }; enum { isConst = true }; enum { isRef = true }; enum { isR_Ref = false }; typedef U Plain; }; template struct Type { enum { isClass = sizeof(fun(0)) == sizeof(double) }; enum { isPointer = false }; enum { isConst = false }; enum { isRef = false }; enum { isR_Ref = true }; typedef U Plain; }; template struct Type { enum { isClass = sizeof(fun(0)) == sizeof(double) }; enum { isPointer = false }; enum { isConst = true }; enum { isRef = false }; enum { isR_Ref = true }; typedef U Plain; }; public: enum { isClass = Type::isClass }; enum { isPointer = Type::isPointer }; enum { isConst = Type::isConst }; enum { isRef = Type::isRef }; enum { isR_Ref = Type::isR_Ref }; typedef typename Type::Plain Plain; }; template class LpromotesR { struct Char2 { char array[2]; }; static R const &makeR(); static char test(L const &); static Char2 test(...); public: LpromotesR() = delete; enum { yes = sizeof(test(makeR())) == sizeof(char) }; }; template struct Use { typedef typename std::conditional< LpromotesR::yes, LHS, RHS>::type type; }; } // FBB #endif bobcat-3.19.01/user/0000755000175000017500000000000012257325714013071 5ustar frankfrankbobcat-3.19.01/user/userid.f0000644000175000017500000000007112223550765014530 0ustar frankfrankinline size_t User::userid() const { return d_uid; } bobcat-3.19.01/user/user.ih0000644000175000017500000000030612222576534014370 0ustar frankfrank#include "user" #include #include #include #include #include #include using namespace FBB; using namespace std; bobcat-3.19.01/user/shell.f0000644000175000017500000000010612223550765014343 0ustar frankfrankinline std::string const &User::shell() const { return d_shell; } bobcat-3.19.01/user/ingroup.cc0000644000175000017500000000062112222600727015052 0ustar frankfrank#include "user.ih" bool User::inGroup(size_t gid, bool useEffective) const { size_t size = getgroups(0, 0); size_t listSize = size + useEffective; gid_t *list = new gid_t[listSize]; size_t nGroups = getgroups(size, list); if (useEffective) list[size] = getegid(); bool ret = find(list, list + nGroups, gid) != list + nGroups; delete[] list; return ret; } bobcat-3.19.01/user/euserid.cc0000644000175000017500000000011412222600727015024 0ustar frankfrank#include "user.ih" size_t User::eUserid() const { return geteuid(); } bobcat-3.19.01/user/user2.cc0000644000175000017500000000043312222600727014430 0ustar frankfrank#include "user.ih" User::User(User &&tmp) : d_name( move(tmp.d_name) ), d_password( move(tmp.d_password) ), d_realname( move(tmp.d_realname) ), d_homedir( move(tmp.d_homedir) ), d_shell( move(tmp.d_shell) ), d_uid(tmp.d_uid), d_gid(tmp.d_gid) {} bobcat-3.19.01/user/egroupid.cc0000644000175000017500000000011412222600727015202 0ustar frankfrank#include "user.ih" size_t User::eGroupid() const { return getegid(); } bobcat-3.19.01/user/password.f0000644000175000017500000000011412223550765015075 0ustar frankfrankinline std::string const &User::password() const { return d_password; } bobcat-3.19.01/user/user0000644000175000017500000000241612223550765013774 0ustar frankfrank#ifndef INCLUDED_BOBCAT_USER #define INCLUDED_BOBCAT_USER #include namespace FBB { class User { std::string d_name; std::string d_password; std::string d_realname; std::string d_homedir; std::string d_shell; size_t d_uid; size_t d_gid; public: User(); User(User &&tmp); User &operator=(User &&tmp); void verify() const; // kept for bacward compatibility size_t eGroupid() const; size_t eUserid() const; size_t groupid() const; // .f bool inGroup(size_t gid, bool useEffective = true) const; size_t userid() const; // .f bool inGroup(size_t gid) const; std::string const &homedir() const; // .f std::string const &name() const; // .f std::string const &password() const; // .f std::string const &realname() const; // .f std::string const &shell() const; // .f }; #include "groupid.f" #include "homedir.f" #include "name.f" #include "password.f" #include "realname.f" #include "shell.f" #include "userid.f" } // FBB #endif bobcat-3.19.01/user/realname.f0000644000175000017500000000011412223550765015017 0ustar frankfrankinline std::string const &User::realname() const { return d_realname; } bobcat-3.19.01/user/driver/0000755000175000017500000000000012222576534014364 5ustar frankfrankbobcat-3.19.01/user/driver/build0000755000175000017500000000023312222576534015407 0ustar frankfrank#!/bin/bash CMD="g++ -o driver -Wall -I../../tmp driver.cc -L../../tmp/lib -lbobcat -s" # CMD="g++ -o driver -Wall driver.cc -lbobcat -s" echo $CMD $CMD bobcat-3.19.01/user/driver/driver.cc0000644000175000017500000000101712222576534016165 0ustar frankfrank#include #include using namespace std; using namespace FBB; int main() { User user; cout << "\n" "name : " << user.name() << "\n" << "password : " << user.password() << "\n" << "user id : " << user.userid() << "\n" << "group id : " << user.groupid() << "\n" << "real name : " << user.realname() << "\n" << "home dir : " << user.homedir() << "\n" << "shell : " << user.shell() << "\n" << endl; } bobcat-3.19.01/user/verify.cc0000644000175000017500000000006112222600727014671 0ustar frankfrank#include "user.ih" void User::verify() const {} bobcat-3.19.01/user/user3.cc0000644000175000017500000000070512222600727014433 0ustar frankfrank//#include "user.ih" // //#include "../iuo/iuo" // //User::User(User const &&tmp) //: // d_name( move(tmp.d_name) ), // d_password( move(tmp.d_password) ), // d_realname( move(tmp.d_realname) ), // d_homedir( move(tmp.d_homedir) ), // d_shell( move(tmp.d_shell) ), // d_uid(tmp.d_uid), // d_gid(tmp.d_gid) //{ // static bool called = false; // deprecated__(called, "User::User(User const &&tmp) is"); //} // // // // // // // bobcat-3.19.01/user/name.f0000644000175000017500000000010412223550765014152 0ustar frankfrankinline std::string const &User::name() const { return d_name; } bobcat-3.19.01/user/homedir.f0000644000175000017500000000011212223550765014660 0ustar frankfrankinline std::string const &User::homedir() const { return d_homedir; } bobcat-3.19.01/user/operatorassign.cc0000644000175000017500000000015212222600727016426 0ustar frankfrank#include "user.ih" User &User::operator=(User &&tmp) { fswap(*this, tmp); return *this; } bobcat-3.19.01/user/groupid.f0000644000175000017500000000007212223550765014707 0ustar frankfrankinline size_t User::groupid() const { return d_gid; } bobcat-3.19.01/user/user1.cc0000644000175000017500000000130412222600727014425 0ustar frankfrank#include "user.ih" User::User() { register size_t uid = getuid(); struct passwd *pwd; while ((pwd = getpwent())) { if (pwd->pw_uid == uid) { d_name = pwd->pw_name; d_password = pwd->pw_passwd; d_uid = pwd->pw_uid; d_gid = pwd->pw_gid; d_realname = pwd->pw_gecos; d_homedir = pwd->pw_dir; if (*d_homedir.rbegin() != '/') d_homedir += '/'; d_shell = pwd->pw_shell; endpwent(); return; } } throw Exception(1) << "Unable to determine actual user information from `/etc/passwd'"; } bobcat-3.19.01/x2a/0000755000175000017500000000000012257325714012605 5ustar frankfrankbobcat-3.19.01/x2a/x2a.ih0000644000175000017500000000021112222576534013613 0ustar frankfrank#include "x2a" #include #include #include #include using namespace std; using namespace FBB; bobcat-3.19.01/x2a/opassign.f0000644000175000017500000000012512223757025014572 0ustar frankfrankinline X2a &X2a::operator=(X2a const &rhs) { str(rhs.str()); return *this; } bobcat-3.19.01/x2a/lastfail.f0000644000175000017500000000006712223757061014553 0ustar frankfrankinline bool X2a::lastFail() { return s_lastFail; } bobcat-3.19.01/x2a/opstring.f0000644000175000017500000000010512223756774014624 0ustar frankfrankinline X2a::operator std::string const() const { return str(); } bobcat-3.19.01/x2a/x2a2.f0000644000175000017500000000011312223756725013526 0ustar frankfrankinline X2a::X2a(X2a const &other) : std::ostringstream(other.str()) {} bobcat-3.19.01/x2a/x2a1.f0000644000175000017500000000024312223756666013535 0ustar frankfranktemplate // initialize from inline X2a::X2a(T const &x) // (insertable) type { s_lastFail = (*this << x).fail(); } bobcat-3.19.01/x2a/driver/0000755000175000017500000000000012222576534014100 5ustar frankfrankbobcat-3.19.01/x2a/driver/build0000755000175000017500000000006212222576534015123 0ustar frankfrank#!/bin/sh g++ -I.. -o driver driver.cc -lbobcat bobcat-3.19.01/x2a/driver/driver.cc0000644000175000017500000000155112222576534015704 0ustar frankfrank/* driver.cc */ #include #include "../x2a" using namespace std; using namespace FBB; int main(int argc, char **argv, char **envp) { string si(X2a(12)); string sd(X2a(12.25)); cout << si << " " << sd << endl; cout << "Two digits behind decimal dot: " << X2a(7, 2) << endl; cout << "Two digits behind decimal dot: " << X2a(7.1, 2) << endl; cout << "Two digits behind decimal dot: " << X2a(7.0 / 3, 2) << endl; cout << "Same, 8 characters wide: " << X2a(7.0 / 3, 8, 2) << endl; cout << " " << "12345678" << endl; X2a first(3); X2a second(4); first = second; cout << "first: " << first << endl; second = second; // auto assignment test cout << "second: " << second << endl; return 0; } /* Output: 12 12.25 */ bobcat-3.19.01/x2a/data.cc0000644000175000017500000000006112222576534014022 0ustar frankfrank#include "x2a.ih" bool X2a::s_lastFail = false; bobcat-3.19.01/x2a/x2a0000644000175000017500000000165512223757146013232 0ustar frankfrank#ifndef INCLUDED_BOBCAT_X2A_ #define INCLUDED_BOBCAT_X2A_ #include #include namespace FBB { class X2a: public std::ostringstream { static bool s_lastFail; public: template // initialize from X2a(T const &x); // (insertable) type 1.f X2a(X2a const &other); // 2.f X2a(double x, size_t behind); X2a(double x, size_t width, size_t behind); X2a &operator=(X2a const &rhs); // opassign.f operator std::string const() const; // opstring.f bool lastFail(); // .f }; #include "x2a1.f" #include "x2a2.f" #include "opstring.f" #include "opassign.f" #include "lastfail.f" // Free Functions #include "opinsert.f" // ostream << X2a } // FBB #endif bobcat-3.19.01/x2a/opinsert.f0000644000175000017500000000014612223757141014614 0ustar frankfrankinline std::ostream &operator<<(std::ostream &ostr, X2a const &x2a) { return ostr << x2a.str(); } bobcat-3.19.01/x2a/x2a2.cc0000644000175000017500000000020212222576534013662 0ustar frankfrank#include "x2a.ih" X2a::X2a(double x, size_t wid, size_t behind) { X2a tmp(x, behind); *this << setw(wid) << tmp.str(); } bobcat-3.19.01/x2a/x2a1.cc0000644000175000017500000000056012222576534013670 0ustar frankfrank#include "x2a.ih" X2a::X2a(double x, size_t behind) { double power = pow(10, static_cast(behind)); *this << round(x * power) / power; string::size_type pos = str().find_first_of('.'); if (pos == string::npos) *this << '.'; else behind -= str().length() - pos - 1; fill_n(ostream_iterator(*this), behind, '0'); } bobcat-3.19.01/xpointer/0000755000175000017500000000000012257325714013763 5ustar frankfrankbobcat-3.19.01/xpointer/destructor.cc0000644000175000017500000000023612222576535016472 0ustar frankfrank#include "xpointer.ih" Xpointer::~Xpointer() { if (!--s_counter) // No more Xpointer objects ? XCloseDisplay(s_theDisplay); } bobcat-3.19.01/xpointer/get.cc0000644000175000017500000000052312222576535015052 0ustar frankfrank#include "xpointer.ih" bool Xpointer::get(int *x, int *y) const { Window rootret; Window child; Window root = DefaultRootWindow(s_theDisplay); unsigned int keys; int dum_x; int dum_y; return XQueryPointer(s_theDisplay, root, &rootret, &child, x, y, &dum_x, &dum_y, &keys); } bobcat-3.19.01/xpointer/set.cc0000644000175000017500000000077712222576535015101 0ustar frankfrank#include "xpointer.ih" bool Xpointer::set(int x, int y) const { Window root = DefaultRootWindow(s_theDisplay); XWindowAttributes XWA; // get root window info if (!XGetWindowAttributes(s_theDisplay, root, &XWA)) return false; // failure return if (x < 0) x += XWA.width; if (y < 0) y += XWA.height; XWarpPointer(s_theDisplay, root, root, 0, 0, XWA.width, XWA.height, x, y); XFlush(s_theDisplay); return true; } bobcat-3.19.01/xpointer/deleter.f0000644000175000017500000000013112223614212015534 0ustar frankfrankinline void Xpointer::deleter(Display *dsp) { if (dsp) XCloseDisplay(dsp); } bobcat-3.19.01/xpointer/driver/0000755000175000017500000000000012224230205015236 5ustar frankfrankbobcat-3.19.01/xpointer/driver/build0000755000175000017500000000071612224227420016274 0ustar frankfrank#!/bin/sh case $1 in (1) g++-4.4 --std=c++0x -c -Wall driver.cc g++-4.4 -o driver *.o ../*.o -lbobcat -lX11 ;; (2) g++ -o driver -Wall -I../../tmp *.cc -lX11 -L../../tmp/lib -lbobcat ;; (3) g++ -o driver -Wall *.cc -lbobcat -lX11 ;; (*) echo " Provide arg 1, 2 or 3: 1: link to .o files in .. 2: link to a created bobcat in ../../tmp/lib 3: link to installed bobcat " ;; esac bobcat-3.19.01/xpointer/driver/driver.cc0000644000175000017500000000136212222576535017063 0ustar frankfrank#include #include "../xpointer" #include #include using namespace std; using namespace FBB; int main(int argc, char **argv) try { if (argc != 3) { cout << "Two arguments required: x and y pixel-pointerlocation" << endl; return 1; } Xpointer xpointer; if (!xpointer.set(A2x(argv[1]), A2x(argv[2]))) throw Errno() << insertable << "Pointer setting failed" << throwable; int x; int y; if (!xpointer.get(&x, &y)) throw Errno() << insertable << "Pointer getting failed" << throwable; cout << "Pointer now at " << x << ", " << y << endl; return 0; } catch (Errno const &err) { cout << err.why() << endl; return 1; } bobcat-3.19.01/xpointer/data.cc0000644000175000017500000000013112222576535015177 0ustar frankfrank#include "xpointer.ih" size_t Xpointer::s_counter = 0; Display *Xpointer::s_theDisplay; bobcat-3.19.01/xpointer/xpointer.cc0000644000175000017500000000036012222576535016142 0ustar frankfrank#include "xpointer.ih" Xpointer::Xpointer() { if (s_counter++) return; // One more object s_theDisplay = XOpenDisplay(0); if (!s_theDisplay) throw Exception(1) << "Can't open the display"; } bobcat-3.19.01/xpointer/verify.cc0000644000175000017500000000007612222576535015602 0ustar frankfrank#include "xpointer.ih" void Xpointer::verify() const {} bobcat-3.19.01/xpointer/xpointer0000644000175000017500000000111112223614554015544 0ustar frankfrank#ifndef INCLUDED_BOBCAT_XPOINTER_ #define INCLUDED_BOBCAT_XPOINTER_ #include #include namespace FBB { class Xpointer { typedef void (*DeleterType)(Display *); static size_t s_counter; static Display *s_theDisplay; public: Xpointer(); ~Xpointer(); void verify() const; // kept for backward compatibility bool set(int x, int y) const; bool get(int *x, int *y) const; private: static void deleter(Display *dsp); // .f }; #include "deleter.f" } // FBB #endif bobcat-3.19.01/xpointer/xpointer.ih0000644000175000017500000000013412222576535016154 0ustar frankfrank#include "xpointer" #include using namespace std; using namespace FBB;