summaryrefslogtreecommitdiff
path: root/libcult
diff options
context:
space:
mode:
Diffstat (limited to 'libcult')
-rw-r--r--libcult/GPLv2340
-rw-r--r--libcult/INSTALL21
-rw-r--r--libcult/LICENSE25
-rw-r--r--libcult/NEWS126
-rw-r--r--libcult/README15
-rw-r--r--libcult/build/bootstrap.make46
-rw-r--r--libcult/build/configuration-dynamic.make3
-rw-r--r--libcult/build/configuration-rules.make18
-rw-r--r--libcult/build/configuration.make28
-rwxr-xr-xlibcult/build/configure47
-rw-r--r--libcult/build/cxx/configuration-dynamic.make14
-rw-r--r--libcult/build/cxx/gnu/configuration-dynamic.make8
-rw-r--r--libcult/build/export/libcult/stub.make10
l---------libcult/build/import/libcult/LICENSE1
-rw-r--r--libcult/build/import/libcult/configuration-rules.make15
-rwxr-xr-xlibcult/build/import/libcult/configure55
-rw-r--r--libcult/build/import/libcult/stub.make30
-rw-r--r--libcult/build/ld/configuration-lib-dynamic.make13
-rw-r--r--libcult/cult/cli/arguments.cxx22
-rw-r--r--libcult/cult/cli/arguments.hxx85
-rw-r--r--libcult/cult/cli/arguments.ixx21
-rw-r--r--libcult/cult/cli/exceptions.hxx136
-rw-r--r--libcult/cult/cli/file-arguments.cxx118
-rw-r--r--libcult/cult/cli/file-arguments.hxx59
-rw-r--r--libcult/cult/cli/mapper.hxx.m465
-rw-r--r--libcult/cult/cli/options-parser.cxx40
-rw-r--r--libcult/cult/cli/options-parser.hxx570
-rw-r--r--libcult/cult/cli/options-parser.ixx12
-rw-r--r--libcult/cult/cli/options-parser.txx34
-rw-r--r--libcult/cult/cli/options-spec.cxx14
-rw-r--r--libcult/cult/cli/options-spec.hxx723
-rw-r--r--libcult/cult/cli/options-spec.ixx12
-rw-r--r--libcult/cult/cli/options-spec.txx320
-rw-r--r--libcult/cult/cli/options.cxx17
-rw-r--r--libcult/cult/cli/options.hxx502
-rw-r--r--libcult/cult/cli/options.ixx12
-rw-r--r--libcult/cult/cli/options.txx320
-rw-r--r--libcult/cult/cli/scanner.cxx17
-rw-r--r--libcult/cult/cli/scanner.hxx132
-rw-r--r--libcult/cult/cli/scanner.ixx12
-rw-r--r--libcult/cult/containers/any.hxx192
-rw-r--r--libcult/cult/containers/any.txx11
-rw-r--r--libcult/cult/containers/deque.hxx166
-rw-r--r--libcult/cult/containers/graph.hxx193
-rw-r--r--libcult/cult/containers/graph.txx313
-rw-r--r--libcult/cult/containers/iterator.hxx227
-rw-r--r--libcult/cult/containers/list.hxx193
-rw-r--r--libcult/cult/containers/map.hxx175
-rw-r--r--libcult/cult/containers/pair.hxx58
-rw-r--r--libcult/cult/containers/set.hxx175
-rw-r--r--libcult/cult/containers/stack.hxx95
-rw-r--r--libcult/cult/containers/vector.hxx164
-rw-r--r--libcult/cult/dr/xdr/input-stream.cxx152
-rw-r--r--libcult/cult/dr/xdr/input-stream.hxx78
-rw-r--r--libcult/cult/dr/xdr/output-stream.cxx222
-rw-r--r--libcult/cult/dr/xdr/output-stream.hxx89
-rw-r--r--libcult/cult/eh/exception.cxx27
-rw-r--r--libcult/cult/eh/exception.hxx25
-rw-r--r--libcult/cult/makefile160
-rw-r--r--libcult/cult/meta/answer.hxx27
-rw-r--r--libcult/cult/meta/class-p.hxx33
-rw-r--r--libcult/cult/meta/polymorphic-p.hxx56
-rw-r--r--libcult/cult/meta/remove-c.hxx27
-rw-r--r--libcult/cult/meta/remove-cv.hxx24
-rw-r--r--libcult/cult/meta/remove-v.hxx27
-rw-r--r--libcult/cult/mm/arch/generic/counter.hxx45
-rw-r--r--libcult/cult/mm/arch/generic/counter.ixx47
-rw-r--r--libcult/cult/mm/arch/i386/counter.hxx43
-rw-r--r--libcult/cult/mm/arch/i386/counter.ixx46
-rw-r--r--libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.hxx43
-rw-r--r--libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx46
-rw-r--r--libcult/cult/mm/bits/evptr.hxx379
-rw-r--r--libcult/cult/mm/bits/shptr.hxx85
-rw-r--r--libcult/cult/mm/buffer.cxx140
-rw-r--r--libcult/cult/mm/buffer.hxx80
-rw-r--r--libcult/cult/mm/counter.cxx14
-rw-r--r--libcult/cult/mm/counter.hxx79
-rw-r--r--libcult/cult/mm/counter.ixx38
-rw-r--r--libcult/cult/mm/evptr.hxx221
-rw-r--r--libcult/cult/mm/exception.hxx31
-rw-r--r--libcult/cult/mm/new.cxx192
-rw-r--r--libcult/cult/mm/new.hxx297
-rw-r--r--libcult/cult/mm/new.ixx36
-rw-r--r--libcult/cult/mm/shptr.hxx139
-rw-r--r--libcult/cult/mm/static-ptr.hxx75
-rw-r--r--libcult/cult/os/exception.cxx13
-rw-r--r--libcult/cult/os/exception.hxx46
-rw-r--r--libcult/cult/os/net/address.cxx37
-rw-r--r--libcult/cult/os/net/address.hxx60
-rw-r--r--libcult/cult/os/net/datagram-socket.cxx26
-rw-r--r--libcult/cult/os/net/datagram-socket.hxx57
-rw-r--r--libcult/cult/os/net/ipv4/address.cxx37
-rw-r--r--libcult/cult/os/net/ipv4/address.hxx143
-rw-r--r--libcult/cult/os/net/ipv4/datagram-socket.cxx20
-rw-r--r--libcult/cult/os/net/ipv4/datagram-socket.hxx282
-rw-r--r--libcult/cult/os/net/ipv4/multicast-socket.cxx19
-rw-r--r--libcult/cult/os/net/ipv4/multicast-socket.hxx133
-rw-r--r--libcult/cult/os/net/multicast-socket.cxx26
-rw-r--r--libcult/cult/os/net/multicast-socket.hxx40
-rw-r--r--libcult/cult/os/net/socket.cxx26
-rw-r--r--libcult/cult/os/net/socket.hxx54
-rw-r--r--libcult/cult/rtti/type-id.hxx52
-rw-r--r--libcult/cult/rtti/type-id.ixx45
-rw-r--r--libcult/cult/rtti/type-id.txx18
-rw-r--r--libcult/cult/rtti/type-info.cxx42
-rw-r--r--libcult/cult/rtti/type-info.hxx147
-rw-r--r--libcult/cult/rtti/type-info.ixx87
-rw-r--r--libcult/cult/sched/condition.cxx49
-rw-r--r--libcult/cult/sched/condition.hxx42
-rw-r--r--libcult/cult/sched/exception.hxx30
-rw-r--r--libcult/cult/sched/lock.cxx13
-rw-r--r--libcult/cult/sched/lock.hxx58
-rw-r--r--libcult/cult/sched/mutex.cxx54
-rw-r--r--libcult/cult/sched/mutex.hxx41
-rw-r--r--libcult/cult/sched/spin.cxx28
-rw-r--r--libcult/cult/sched/spin.hxx41
-rw-r--r--libcult/cult/sched/spin.ixx43
-rw-r--r--libcult/cult/sched/thread.cxx211
-rw-r--r--libcult/cult/sched/thread.hxx86
-rw-r--r--libcult/cult/trace/log.cxx49
-rw-r--r--libcult/cult/trace/log.hxx51
-rw-r--r--libcult/cult/trace/log.ixx20
-rw-r--r--libcult/cult/trace/null/record.ixx45
-rw-r--r--libcult/cult/trace/null/record.txx18
-rw-r--r--libcult/cult/trace/null/stream.ixx67
-rw-r--r--libcult/cult/trace/null/stream.txx18
-rw-r--r--libcult/cult/trace/record.hxx86
-rw-r--r--libcult/cult/trace/record.ixx45
-rw-r--r--libcult/cult/trace/record.txx19
-rw-r--r--libcult/cult/trace/stream.hxx74
-rw-r--r--libcult/cult/trace/stream.ixx76
-rw-r--r--libcult/cult/trace/stream.txx19
-rw-r--r--libcult/cult/types.hxx14
-rw-r--r--libcult/cult/types/evptr.hxx21
-rw-r--r--libcult/cult/types/fundamental.hxx175
-rw-r--r--libcult/cult/types/shptr.hxx21
-rw-r--r--libcult/cult/types/string.hxx397
-rw-r--r--libcult/documentation/BUGS2
-rw-r--r--libcult/documentation/CORE14
-rw-r--r--libcult/documentation/DESIGN12
-rw-r--r--libcult/documentation/DOC1
-rw-r--r--libcult/documentation/NOTES3
-rw-r--r--libcult/documentation/RELEASE1
-rw-r--r--libcult/documentation/THOGHTS1
-rw-r--r--libcult/documentation/TODO3
-rw-r--r--libcult/documentation/TODO-CLI7
-rw-r--r--libcult/documentation/TODO-EH5
-rw-r--r--libcult/documentation/TODO-META2
-rw-r--r--libcult/documentation/TODO-MM3
-rw-r--r--libcult/documentation/TODO-SCHED12
-rw-r--r--libcult/documentation/cli/index.xhtml106
-rw-r--r--libcult/documentation/default.css160
-rw-r--r--libcult/documentation/dr/index.xhtml57
-rw-r--r--libcult/documentation/eh/index.xhtml106
-rw-r--r--libcult/documentation/index.xhtml78
-rw-r--r--libcult/documentation/meta/index.xhtml70
-rw-r--r--libcult/documentation/mm/index.xhtml77
-rw-r--r--libcult/documentation/os/index.xhtml57
-rw-r--r--libcult/documentation/rtti/index.xhtml57
-rw-r--r--libcult/documentation/sched/index.xhtml57
-rw-r--r--libcult/documentation/trace/index.xhtml102
-rw-r--r--libcult/documentation/types/index.xhtml56
-rw-r--r--libcult/examples/cli/cli.cxx65
-rw-r--r--libcult/examples/cli/makefile48
-rw-r--r--libcult/examples/dr/xdr/makefile49
-rw-r--r--libcult/examples/dr/xdr/xdr.cxx87
-rw-r--r--libcult/examples/makefile36
-rw-r--r--libcult/examples/mm/shptr/makefile48
-rw-r--r--libcult/examples/mm/shptr/shptr.cxx73
-rw-r--r--libcult/examples/mm/transfer/makefile48
-rw-r--r--libcult/examples/mm/transfer/transfer.cxx117
-rw-r--r--libcult/examples/os/net/ipv4/datagram/client.cxx66
-rw-r--r--libcult/examples/os/net/ipv4/datagram/makefile55
-rw-r--r--libcult/examples/os/net/ipv4/datagram/protocol.hxx20
-rw-r--r--libcult/examples/os/net/ipv4/datagram/server.cxx123
-rw-r--r--libcult/examples/os/net/ipv4/multicast/client.cxx66
-rw-r--r--libcult/examples/os/net/ipv4/multicast/makefile55
-rw-r--r--libcult/examples/os/net/ipv4/multicast/protocol.hxx20
-rw-r--r--libcult/examples/os/net/ipv4/multicast/server.cxx134
-rw-r--r--libcult/examples/sched/cancel/cancel.cxx63
-rw-r--r--libcult/examples/sched/cancel/makefile48
-rw-r--r--libcult/examples/sched/main/main.cxx43
-rw-r--r--libcult/examples/sched/main/makefile48
-rw-r--r--libcult/examples/trace/makefile48
-rw-r--r--libcult/examples/trace/trace.cxx51
-rw-r--r--libcult/makefile15
-rw-r--r--libcult/version1
187 files changed, 14840 insertions, 0 deletions
diff --git a/libcult/GPLv2 b/libcult/GPLv2
new file mode 100644
index 0000000..3912109
--- /dev/null
+++ b/libcult/GPLv2
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/libcult/INSTALL b/libcult/INSTALL
new file mode 100644
index 0000000..72c7a29
--- /dev/null
+++ b/libcult/INSTALL
@@ -0,0 +1,21 @@
+Prerequisites
+
+ build-time:
+
+ - build >= 0.3.2 http://www.codesynthesis.com/projects/build/
+ - g++ >= 3.4.3 http://gcc.gnu.org
+
+
+Building libcult
+
+ To build in the source directory simply say `make'. You can also
+ build in a separate directory, e.g.,
+
+ $ mkdir libcult-i686-pc-linux-gnu
+ $ cd libcult-i686-pc-linux-gnu
+ $ make -f ../libcult-x.y.z/makefile
+
+
+Installing libcult
+
+ Not supported in this version.
diff --git a/libcult/LICENSE b/libcult/LICENSE
new file mode 100644
index 0000000..3204be4
--- /dev/null
+++ b/libcult/LICENSE
@@ -0,0 +1,25 @@
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+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 details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+In addition, as a special exception, Boris Kolpackov gives permission
+to combine this library with other incompatibly-licensed modules in a
+single program and to distribute such a combination provided that there
+is no use of the functionality implemented by this library, directly
+or indirectly, by such modules. You must obey the GNU General Public
+License version 2 in all respects for all of the code used other than
+such modules. In particular, the resulting program must be licensed
+under a license compatible with the GNU General Public License version
+2. If you modify this copy of the library, you may extend this exception
+to your version of the library, but you are not obligated to do so. If
+you do not wish to do so, delete this exception statement from your
+version.
diff --git a/libcult/NEWS b/libcult/NEWS
new file mode 100644
index 0000000..2924310
--- /dev/null
+++ b/libcult/NEWS
@@ -0,0 +1,126 @@
+Version 1.4.6
+
+ * Add support for deleting graph nodes.
+
+Version 1.4.5
+
+ * Add support for libcult bundling.
+
+ * Suppress warning in exception inheritance.
+
+Version 1.4.4
+
+ * Add an exception to the licensing terms to allow combining with
+ incompatibly-licensed modules in a single program. See the LICENSE
+ file for details.
+
+Version 1.4.3
+
+ * Remove leading and trailing whitespaces from arguments in
+ CLI::FileArguments.
+
+Version 1.4.2
+
+ * Support for stripping leading and (some) trailing whitespaces
+ in the FileArguments class.
+
+Version 1.4.1
+
+ * The number of options in CLI was increased from 80 to 100.
+
+ * Fixed a bug in import stubs.
+
+ * Got rid of warnings reported by g++-4.3.
+
+Version 1.4.0
+
+ * New arguments scanners: BasicArguments and FileArguments.
+
+ * Conversion to narrow format in StringTemplate.
+
+Version 1.3.0
+
+ * Upgraded to build-0.3.0.
+
+Version 1.2.3
+
+ * Compilation time and generated code size optimizations in CLI.
+
+ * Set of typedefs in Containers::Iterator to be compatible with
+ std::iterator_traits.
+
+Version 1.2.2
+
+ * A bug in Cult::String has been fixed.
+
+Version 1.2.1
+
+ * The number of options in CLI was increased from 50 to 80.
+
+ * A bug in Containers::Any has been fixed.
+
+
+Version 1.2.0
+
+ * Containers::Graph now supports removal of edges.
+
+ * Added missing member functions to container wrappers.
+
+
+Version 1.1.0
+
+ * Generic, std::istream-based parser has been added to CLI parsers.
+
+ * Containers::IteratorAdapter has been modified to use
+ std::iterator_traits for better portability.
+
+ * Threading, networking and data representation subsystems were
+ made optional.
+
+
+Version 1.0.6
+
+ * Upgraded to build-0.2.1.
+
+
+Version 1.0.5
+
+ * Moved to the build 0.2 series.
+
+
+Version 1.0.4
+
+ * Containers::Graph has been extended to support more arguments in
+ the new_node() and new_edge() functions.
+
+
+Version 1.0.3
+
+ * MM::Counter has been re-implemented to use size_t instead of int
+ on i386 and x86_64.
+
+ * Containers::Graph has been extended to support more arguments in
+ the new_node() function.
+
+ * Fixed a bug in CLI::OptionsSpec that resulted in a wrong default
+ initialization of options.
+
+
+Version 1.0.2
+
+ * New Containers::List wrapper for std::list.
+
+ * CLI::OptionsParser now skips arguments instead of erasing them when
+ UnknownMode is set to skip.
+
+
+Version 1.0.1
+
+ * WideString can now be initialized with NarrowString and NarrowChar const*.
+
+ * Build system improvements.
+
+
+Version 1.0.0
+
+ * First public release.
diff --git a/libcult/README b/libcult/README
new file mode 100644
index 0000000..2227831
--- /dev/null
+++ b/libcult/README
@@ -0,0 +1,15 @@
+libcult is a collection of c++ libraries that were designed to form
+a cohesive union of clean, simple and readable c++ code that uses
+the most powerful mechanisms available on the GNU development platform.
+
+See the NEWS file for the user-visible changes from the previous release.
+
+See the LICENSE file for distribution conditions.
+
+See the INSTALL file for prerequisites and installation instructions.
+
+See the documentation/index.xhtml file for documentation.
+
+The project page is at http://kolpackov.net/projects/c++/libcult/.
+
+Send bug reports or any other feedback to boris@kolpackov.net .
diff --git a/libcult/build/bootstrap.make b/libcult/build/bootstrap.make
new file mode 100644
index 0000000..fc9cd38
--- /dev/null
+++ b/libcult/build/bootstrap.make
@@ -0,0 +1,46 @@
+# file : build/bootstrap.make
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+project_name := libcult
+
+# First try to include the bundled bootstrap.make if it exist. If that
+# fails, let make search for the external bootstrap.make.
+#
+build := build-0.3
+
+-include $(dir $(lastword $(MAKEFILE_LIST)))../../$(build)/bootstrap.make
+
+ifeq ($(patsubst %build/bootstrap.make,,$(lastword $(MAKEFILE_LIST))),)
+include $(build)/bootstrap.make
+endif
+
+# Aliases
+#
+.PHONY: $(out_base)/ \
+ $(out_base)/.test \
+ $(out_base)/.clean
+
+ifdef %interactive%
+
+.PHONY: test clean
+
+test: $(out_base)/.test
+clean: $(out_base)/.clean
+
+ifneq ($(filter $(.DEFAULT_GOAL),test clean),)
+.DEFAULT_GOAL :=
+endif
+
+endif
+
+# Don't include dependency info for certain targets.
+#
+define include-dep
+$(call -include,$1)
+endef
+
+ifneq ($(filter $(MAKECMDGOALS),clean cleandoc disfigure),)
+include-dep =
+endif
diff --git a/libcult/build/configuration-dynamic.make b/libcult/build/configuration-dynamic.make
new file mode 100644
index 0000000..e027b0b
--- /dev/null
+++ b/libcult/build/configuration-dynamic.make
@@ -0,0 +1,3 @@
+cult_dr := n
+cult_threads := n
+cult_network := n
diff --git a/libcult/build/configuration-rules.make b/libcult/build/configuration-rules.make
new file mode 100644
index 0000000..e6df883
--- /dev/null
+++ b/libcult/build/configuration-rules.make
@@ -0,0 +1,18 @@
+# file : build/configuration-rules.make
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2006-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+$(dcf_root)/configuration-dynamic.make: | $(dcf_root)/.
+ $(call message,,$(scf_root)/configure $@)
+
+ifndef %foreign%
+
+disfigure::
+ $(call message,rm $$1,rm -f $$1,$(dcf_root)/configuration-dynamic.make)
+
+endif
+
+ifeq ($(.DEFAULT_GOAL),$(dcf_root)/configuration-dynamic.make)
+.DEFAULT_GOAL :=
+endif
diff --git a/libcult/build/configuration.make b/libcult/build/configuration.make
new file mode 100644
index 0000000..b8724c8
--- /dev/null
+++ b/libcult/build/configuration.make
@@ -0,0 +1,28 @@
+# file : build/configuration.make
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2006-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+$(call include-once,$(scf_root)/configuration-rules.make,$(dcf_root))
+
+
+# Dynamic configuration.
+#
+cult_dr :=
+cult_threads :=
+cult_network :=
+
+
+$(call -include,$(dcf_root)/configuration-dynamic.make)
+
+ifdef cult_dr
+
+$(out_root)/%: cult_threads := $(cult_threads)
+$(out_root)/%: cult_network := $(cult_network)
+$(out_root)/%: cult_dr := $(cult_dr)
+
+else
+
+.NOTPARALLEL:
+
+endif
diff --git a/libcult/build/configure b/libcult/build/configure
new file mode 100755
index 0000000..4473653
--- /dev/null
+++ b/libcult/build/configure
@@ -0,0 +1,47 @@
+#! /usr/bin/env bash
+
+# file : build/configure
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2006-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+# $1 out file
+#
+# bld_root - build root
+# project_name - project name
+#
+
+source $bld_root/dialog.bash
+
+
+$echo
+$echo
+$echo "configuring '$project_name'"
+$echo
+$echo
+
+
+$echo
+$echo "Would you like to build a multi-threaded version of '$project_name'?"
+$echo
+
+threads=`read_y_n y`
+
+
+$echo
+$echo "Would you like to build the network subsystem of '$project_name'?"
+$echo
+
+network=`read_y_n y`
+
+
+$echo
+$echo "Would you like to build the data representation subsystem of '$project_name'?"
+$echo
+
+dr=`read_y_n y`
+
+
+echo "cult_dr := $dr" >$1
+echo "cult_threads := $threads" >>$1
+echo "cult_network := $network" >>$1
diff --git a/libcult/build/cxx/configuration-dynamic.make b/libcult/build/cxx/configuration-dynamic.make
new file mode 100644
index 0000000..568ab40
--- /dev/null
+++ b/libcult/build/cxx/configuration-dynamic.make
@@ -0,0 +1,14 @@
+cxx_id := gnu
+cxx_optimize := n
+cxx_debug := n
+cxx_rpath := n
+cxx_pp_extra_options := $(CPPFLAGS)
+cxx_extra_options := $(CXXFLAGS)
+cxx_ld_extra_options := $(LDFLAGS)
+cxx_extra_libs := $(LIBS)
+
+r := $(shell echo $(LDFLAGS) | sed -e 's/-L *\([^ ]*\)/-L\1/g')
+r := $(patsubst -L%,%,$(filter -L%,$(r)))
+r := $(shell echo $(r) | sed -e 's/ /:/g')
+
+cxx_extra_lib_paths := $(r)
diff --git a/libcult/build/cxx/gnu/configuration-dynamic.make b/libcult/build/cxx/gnu/configuration-dynamic.make
new file mode 100644
index 0000000..f3fe64d
--- /dev/null
+++ b/libcult/build/cxx/gnu/configuration-dynamic.make
@@ -0,0 +1,8 @@
+ifneq ($(CXX),)
+cxx_gnu := $(CXX)
+else
+cxx_gnu := g++
+endif
+
+cxx_gnu_libraries :=
+cxx_gnu_optimization_options :=
diff --git a/libcult/build/export/libcult/stub.make b/libcult/build/export/libcult/stub.make
new file mode 100644
index 0000000..354b083
--- /dev/null
+++ b/libcult/build/export/libcult/stub.make
@@ -0,0 +1,10 @@
+# file : build/export/libcult/stub.make
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+$(call include-once,$(src_root)/cult/makefile,$(out_root))
+
+$(call export,\
+ l: $(out_root)/cult/cult.l,\
+ cpp-options: $(out_root)/cult/cult.l.cpp-options)
diff --git a/libcult/build/import/libcult/LICENSE b/libcult/build/import/libcult/LICENSE
new file mode 120000
index 0000000..5853aae
--- /dev/null
+++ b/libcult/build/import/libcult/LICENSE
@@ -0,0 +1 @@
+../../../LICENSE \ No newline at end of file
diff --git a/libcult/build/import/libcult/configuration-rules.make b/libcult/build/import/libcult/configuration-rules.make
new file mode 100644
index 0000000..5d8c939
--- /dev/null
+++ b/libcult/build/import/libcult/configuration-rules.make
@@ -0,0 +1,15 @@
+# file : build/import/libcult/configuration-rules.make
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+$(dcf_root)/import/libcult/configuration-dynamic.make: | $(dcf_root)/import/libcult/.
+ $(call message,,$(scf_root)/import/libcult/configure $@)
+
+ifndef %foreign%
+
+disfigure::
+ $(call message,rm $(dcf_root)/import/libcult/configuration-dynamic.make,\
+rm -f $(dcf_root)/import/libcult/configuration-dynamic.make)
+
+endif
diff --git a/libcult/build/import/libcult/configure b/libcult/build/import/libcult/configure
new file mode 100755
index 0000000..0eb142f
--- /dev/null
+++ b/libcult/build/import/libcult/configure
@@ -0,0 +1,55 @@
+#! /usr/bin/env bash
+
+# file : build/import/libcult/configure
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+
+# $1 - out file
+#
+# bld_root - build root
+# project_name - project name
+#
+
+source $bld_root/dialog.bash
+
+
+$echo
+$echo "Configuring external dependency on 'libcult' for '$project_name'."
+$echo
+
+$echo
+$echo "Would you like to configure dependency on the installed "
+$echo "version of 'libcult' as opposed to the development build?"
+$echo
+
+installed=`read_y_n y`
+
+path=
+
+if [ "$installed" = "n" ]; then
+
+$echo
+$echo "Please enter the src_root for 'libcult'."
+$echo
+
+src_root=`read_path --directory --exist`
+
+$echo
+$echo "Please enter the out_root for 'libcult'."
+$echo
+
+out_root=`read_path --directory $src_root`
+
+fi
+
+echo libcult_installed := $installed >$1
+
+if [ "$installed" = "n" ]; then
+
+echo src_root := $src_root >>$1
+echo scf_root := \$\(src_root\)/build >>$1
+echo out_root := $out_root >>$1
+
+fi
diff --git a/libcult/build/import/libcult/stub.make b/libcult/build/import/libcult/stub.make
new file mode 100644
index 0000000..7469300
--- /dev/null
+++ b/libcult/build/import/libcult/stub.make
@@ -0,0 +1,30 @@
+# file : build/import/libcult/stub.make
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+$(call include-once,$(scf_root)/import/libcult/configuration-rules.make,$(dcf_root))
+
+libcult_installed :=
+
+$(call -include,$(dcf_root)/import/libcult/configuration-dynamic.make)
+
+ifdef libcult_installed
+
+ifeq ($(libcult_installed),y)
+
+$(call export,l: -lcult,cpp-options: )
+
+else
+
+# Include export stub.
+#
+$(call include,$(scf_root)/export/libcult/stub.make)
+
+endif
+
+else
+
+.NOTPARALLEL:
+
+endif
diff --git a/libcult/build/ld/configuration-lib-dynamic.make b/libcult/build/ld/configuration-lib-dynamic.make
new file mode 100644
index 0000000..74c8885
--- /dev/null
+++ b/libcult/build/ld/configuration-lib-dynamic.make
@@ -0,0 +1,13 @@
+ld_lib_type := archive
+
+ifneq ($(AR),)
+ld_lib_ar := $(AR)
+else
+ld_lib_ar := ar
+endif
+
+ifneq ($(RANLIB),)
+ld_lib_ranlib := $(RANLIB)
+else
+ld_lib_ranlib := ranlib
+endif
diff --git a/libcult/cult/cli/arguments.cxx b/libcult/cult/cli/arguments.cxx
new file mode 100644
index 0000000..28805d0
--- /dev/null
+++ b/libcult/cult/cli/arguments.cxx
@@ -0,0 +1,22 @@
+// file : cult/cli/arguments.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/cli/arguments.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ Arguments::
+ ~Arguments ()
+ {
+ }
+
+ BasicArguments::
+ ~BasicArguments ()
+ {
+ }
+ }
+}
diff --git a/libcult/cult/cli/arguments.hxx b/libcult/cult/cli/arguments.hxx
new file mode 100644
index 0000000..5381172
--- /dev/null
+++ b/libcult/cult/cli/arguments.hxx
@@ -0,0 +1,85 @@
+// file : cult/cli/arguments.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CLI_ARGUMENTS_HXX
+#define CULT_CLI_ARGUMENTS_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/cli/exceptions.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ class Arguments: public NonCopyable
+ {
+ public:
+ virtual
+ ~Arguments ();
+
+ public:
+ class Bounds: public virtual Exception {};
+
+ virtual Size
+ size () const = 0;
+
+ virtual Char const*
+ operator[] (Index) const = 0;
+
+ virtual Void
+ erase (Index) = 0;
+ };
+
+ class BasicArguments: public Arguments
+ {
+ public:
+ virtual
+ ~BasicArguments ();
+
+ BasicArguments (Int& argc, Char** argv);
+
+ public:
+ virtual Size
+ size () const
+ {
+ return static_cast<Size> (argc_);
+ }
+
+ virtual Char const*
+ operator[] (Index i) const
+ {
+ if (i >= size ())
+ throw Bounds ();
+
+ return argv_[i];
+ }
+
+ virtual Void
+ erase (Index i)
+ {
+ if (i >= size ())
+ throw Bounds ();
+
+ for (++i; i < size (); ++i)
+ {
+ argv_[i - 1] = argv_[i];
+ }
+
+ --argc_;
+
+ argv_[argc_] = 0;
+ }
+
+ private:
+ Int& argc_;
+ Char** argv_;
+ };
+ }
+}
+
+#include <cult/cli/arguments.ixx>
+
+#endif // CULT_CLI_ARGUMENTS_HXX
diff --git a/libcult/cult/cli/arguments.ixx b/libcult/cult/cli/arguments.ixx
new file mode 100644
index 0000000..b05295d
--- /dev/null
+++ b/libcult/cult/cli/arguments.ixx
@@ -0,0 +1,21 @@
+// file : cult/cli/arguments.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cassert>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ inline
+ BasicArguments::
+ BasicArguments (Int& argc, Char** argv)
+ : argc_ (argc), argv_ (argv)
+ {
+ assert (argc > 0);
+ }
+ }
+}
+
diff --git a/libcult/cult/cli/exceptions.hxx b/libcult/cult/cli/exceptions.hxx
new file mode 100644
index 0000000..886e008
--- /dev/null
+++ b/libcult/cult/cli/exceptions.hxx
@@ -0,0 +1,136 @@
+// file : cult/cli/exceptions.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CLI_EXCEPTIONS_HXX
+#define CULT_CLI_EXCEPTIONS_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/eh/exception.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ //
+ //
+ class Exception: public virtual EH::Exception
+ {
+ };
+
+ // Exception for FileArguments class.
+ //
+ class OptionFile: public virtual Exception
+ {
+ public:
+ ~OptionFile () throw ()
+ {
+ }
+
+ OptionFile (String const& description)
+ : description_ (description)
+ {
+ }
+
+ OptionFile (String const& value,
+ String const& description)
+ : value_ (value), description_ (description)
+ {
+ }
+
+ String const&
+ value () const
+ {
+ return value_;
+ }
+
+ String const&
+ description () const
+ {
+ return description_;
+ }
+
+ private:
+ String value_;
+ String description_;
+ };
+
+ //
+ //
+ class UnexpectedOption: public virtual Exception
+ {
+ public:
+ ~UnexpectedOption () throw ()
+ {
+ }
+
+ UnexpectedOption (String const& option)
+ : option_ (option)
+ {
+ }
+
+ String const&
+ option () const
+ {
+ return option_;
+ }
+
+ private:
+ String option_;
+ };
+
+
+ //
+ //
+ class UnexpectedArgument: public virtual Exception
+ {
+ public:
+ ~UnexpectedArgument () throw ()
+ {
+ }
+
+ UnexpectedArgument (String const& argument)
+ : argument_ (argument)
+ {
+ }
+
+ String const&
+ argument () const
+ {
+ return argument_;
+ }
+
+ private:
+ String argument_;
+ };
+
+
+ //
+ //
+ class OptionFormat: public virtual Exception
+ {
+ public:
+ ~OptionFormat () throw ()
+ {
+ }
+
+ OptionFormat (String const& option)
+ : option_ (option)
+ {
+ }
+
+ String const&
+ option () const
+ {
+ return option_;
+ }
+
+ private:
+ String option_;
+ };
+ }
+}
+
+#endif // CULT_CLI_EXCEPTIONS_HXX
diff --git a/libcult/cult/cli/file-arguments.cxx b/libcult/cult/cli/file-arguments.cxx
new file mode 100644
index 0000000..4f082dc
--- /dev/null
+++ b/libcult/cult/cli/file-arguments.cxx
@@ -0,0 +1,118 @@
+// file : cult/cli/file-arguments.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cstring> // strcmp
+#include <fstream>
+
+#include <cult/cli/file-arguments.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ FileArguments::
+ ~FileArguments ()
+ {
+ }
+
+ FileArguments::
+ FileArguments (Int argc, Char const* const* argv, Char const* op)
+ {
+ using namespace std;
+
+ if (argc == 0)
+ return;
+
+ args_.push_back (argv[0]);
+
+ Boolean skip (false);
+
+ for (Int i (1); i < argc; ++i)
+ {
+ if (!skip)
+ {
+ if (strcmp (argv[i], "--") == 0)
+ {
+ skip = true;
+ }
+ else if (strcmp (argv[i], op) == 0)
+ {
+ ++i;
+
+ if (i >= argc)
+ throw OptionFile ("missing file name");
+
+ ifstream is (argv[i]);
+
+ if (!is.is_open ())
+ throw OptionFile (argv[i], "unable to open in read mode");
+
+ while (!is.eof ())
+ {
+ String line;
+ getline (is, line);
+
+ if (is.fail () && !is.eof ())
+ throw OptionFile (argv[i], "read failure");
+
+ Size size (line.size ());
+
+ // Trim the line from leading and trailing whitespaces.
+ //
+ if (size != 0)
+ {
+ const Char* f (line.data ());
+ const Char* l (f + size);
+
+ const Char* of (f);
+ while (f < l && (*f == ' ' || *f == '\t' || *f == '\r'))
+ ++f;
+
+ --l;
+
+ const Char* ol (l);
+ while (l > f && (*l == ' ' || *l == '\t' || *l == '\r'))
+ --l;
+
+ if (f != of || l != ol)
+ line = f <= l ? String (f, l - f + 1) : String ();
+ }
+
+ if (line.empty () || line[0] == '#')
+ continue; // Ignore empty lines, those that start with #
+
+ Size pos (line.find (' '));
+
+ if (pos == String::npos)
+ args_.push_back (line);
+ else
+ {
+ Size size (line.size ());
+
+ args_.push_back (String (line, 0, pos));
+
+ // Skip leading whitespaces in the argument.
+ //
+ for (pos++; pos < size; pos++)
+ {
+ Char c (line[pos]);
+
+ if (c != ' ' && c != '\t' && c != '\r')
+ break;
+ }
+
+ args_.push_back (String (line, pos));
+ }
+ }
+
+ continue;
+ }
+ }
+
+ args_.push_back (argv[i]);
+ }
+ }
+ }
+}
diff --git a/libcult/cult/cli/file-arguments.hxx b/libcult/cult/cli/file-arguments.hxx
new file mode 100644
index 0000000..e14f53c
--- /dev/null
+++ b/libcult/cult/cli/file-arguments.hxx
@@ -0,0 +1,59 @@
+// file : cult/cli/file-arguments.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CLI_FILE_ARGUMENTS_HXX
+#define CULT_CLI_FILE_ARGUMENTS_HXX
+
+#include <cult/types.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/exceptions.hxx>
+#include <cult/cli/arguments.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ class FileArguments: public Arguments
+ {
+ public:
+ virtual
+ ~FileArguments ();
+
+ FileArguments (Int argc,
+ Char const* const* argv,
+ Char const* file_option);
+ public:
+ virtual Size
+ size () const
+ {
+ return args_.size ();
+ }
+
+ virtual Char const*
+ operator[] (Index i) const
+ {
+ if (i >= size ())
+ throw Bounds ();
+
+ return args_[i].c_str ();
+ }
+
+ virtual Void
+ erase (Index i)
+ {
+ if (i >= size ())
+ throw Bounds ();
+
+ args_.erase (args_.begin () + i);
+ }
+
+ private:
+ Containers::Vector<String> args_;
+ };
+ }
+}
+
+#endif // CULT_CLI_FILE_ARGUMENTS_HXX
diff --git a/libcult/cult/cli/mapper.hxx.m4 b/libcult/cult/cli/mapper.hxx.m4
new file mode 100644
index 0000000..7ac6760
--- /dev/null
+++ b/libcult/cult/cli/mapper.hxx.m4
@@ -0,0 +1,65 @@
+divert(-1)
+
+# file : cult/cli/mapper.hxx.m4
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+define(`N', 100)
+
+define(`forloop',
+ `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')')
+
+define(`_forloop',
+ `$4`'ifelse($1, `$3', ,
+ `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')')
+
+define(`specialization',`
+template
+<
+forloop(`i', 1, $1, ` char const* x`'i, typename Y`'i`'ifelse(i, $1, ,`,')
+')dnl
+>
+struct Mapper
+<
+forloop(`i', 1, $1, ` x`'i, Y`'i,
+')dnl
+forloop(`i', $1, N, ` null, Null`'ifelse(i, N, ,`,')
+')dnl
+>
+{
+`#ifdef __GNUC__'
+forloop(`i', 1, $1, ` static Y`'i f (Tag<x`'i>*);
+')dnl
+
+ template <char const* x>
+ struct Selector
+ {
+ typedef typeof (Mapper::f ((Tag<x>*) (0))) Type;
+ };
+`#else'
+ template <char const* x>
+ struct Selector
+ {
+ typedef typename if_<same<x, x1>::r, Y1,ifelse($1, 1, ` Void', `
+ typename Mapper
+ <
+forloop(`i', 2, $1, ` x`'i, Y`'i`'ifelse(i, $1, ,`,')
+') >::template Selector<x>::Type')>::Type Type;
+ };
+`#endif'
+};
+')
+
+divert(0)dnl
+
+template
+<
+forloop(`i', 1, incr(N),
+ ` char const* x`'i`'ifelse(i, 1, ,`= null'), dnl
+typename Y`'i`'ifelse(i, 1, ,`= Null')`'ifelse(i, incr(N), ,`,')
+')dnl
+>
+struct Mapper;
+
+forloop(`n', 1, N, `specialization(n)')
diff --git a/libcult/cult/cli/options-parser.cxx b/libcult/cult/cli/options-parser.cxx
new file mode 100644
index 0000000..4a2b6b3
--- /dev/null
+++ b/libcult/cult/cli/options-parser.cxx
@@ -0,0 +1,40 @@
+// file : cult/cli/options-parser.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/cli/options-parser.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ Trace::Stream OptionsParserBase::tout ("Cult::CLI::OptionsParser", 7);
+
+
+ // OptionParserBooleanBase
+ //
+ Boolean OptionParserBooleanBase::
+ parse (Char const*, Scanner&)
+ {
+ return true;
+ }
+
+ // OptionParserStringBase
+ //
+ String OptionParserStringBase::
+ parse (Char const* o, Scanner& s)
+ {
+ Char const* v (s.next ());
+
+ if (v == Scanner::eos)
+ {
+ //@@ "expected string literal after --option"?
+ //
+ throw OptionFormat (o);
+ }
+
+ return v;
+ }
+ }
+}
diff --git a/libcult/cult/cli/options-parser.hxx b/libcult/cult/cli/options-parser.hxx
new file mode 100644
index 0000000..4068fa6
--- /dev/null
+++ b/libcult/cult/cli/options-parser.hxx
@@ -0,0 +1,570 @@
+// file : cult/cli/options-parser.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CLI_OPTIONS_PARSER_HXX
+#define CULT_CLI_OPTIONS_PARSER_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <cult/trace/stream.hxx>
+
+#include <cult/cli/exceptions.hxx>
+#include <cult/cli/scanner.hxx>
+#include <cult/cli/options-spec.hxx>
+
+#include <sstream>
+
+//@! which types should be NonCopyable
+
+namespace Cult
+{
+ namespace CLI
+ {
+ struct UnknownMode
+ {
+ enum Value
+ {
+ skip,
+ stop,
+ fail
+ };
+ };
+
+ template <typename T>
+ struct OptionParserBase
+ {
+ T
+ parse (Char const* o, Scanner& s);
+ };
+
+ template <typename Spec>
+ struct OptionParser: OptionParserBase<typename Spec::Type>
+ {
+ OptionParser (Spec const&)
+ {
+ }
+ };
+
+ template<Char const* o, typename T>
+ class OptionParser<OptionSpec<o, Containers::Vector<T> > >
+ {
+ public:
+ OptionParser (OptionSpec<o, Containers::Vector<T> > const&)
+ : impl_ (OptionSpec<o, T> ())
+ {
+ }
+
+ T
+ parse (Char const* k, Scanner& s)
+ {
+ return impl_.parse (k, s);
+ }
+
+ private:
+ OptionParser<OptionSpec<o, T> > impl_;
+ };
+
+ struct OptionParserBooleanBase
+ {
+ Boolean
+ parse (Char const*, Scanner& s);
+ };
+
+ template<Char const* o>
+ struct OptionParser<OptionSpec<o, Boolean> >: OptionParserBooleanBase
+ {
+ OptionParser (OptionSpec<o, Boolean> const&)
+ {
+ }
+ };
+
+ struct OptionParserStringBase
+ {
+ String
+ parse (Char const*, Scanner& s);
+ };
+
+ template<Char const* o>
+ struct OptionParser<OptionSpec<o, String> >: OptionParserStringBase
+ {
+ OptionParser (OptionSpec<o, String> const&)
+ {
+ }
+ };
+
+ //
+ //
+ //
+
+ class OptionsParserBase
+ {
+ protected:
+ struct GlueBase
+ {
+ // I am using Void* here to (significantly) reduce the length
+ // on the object file symbols.
+ //
+ virtual Void
+ operator() (Char const*, Scanner&, Void* options) = 0;
+ };
+
+ static Trace::Stream tout;
+ };
+
+ template <typename Spec>
+ class OptionsParser : OptionsParserBase
+ {
+ typedef
+ Containers::Map<String, Evptr<GlueBase> >
+ Map;
+
+ template <typename>
+ struct Glue;
+
+ template <Char const* k, typename T>
+ struct Glue<OptionSpec<k, T> > : GlueBase
+ {
+ Glue (OptionSpec<k, T> const& spec)
+ : parser_ (spec)
+ {
+ }
+
+ virtual Void
+ operator() (Char const* o, Scanner& scan, Void* options)
+ {
+ typedef typename Spec::Options Options;
+
+ Options& ops (*reinterpret_cast<Options*> (options));
+
+ ops.template value<k> () = parser_.parse (o, scan);
+ }
+
+ private:
+ OptionParser<OptionSpec<k, T> > parser_;
+ };
+
+ //@@ It's bad that I also have to specialize Glue. Need to redesign
+ // this.
+ //
+ template <Char const* k, typename T>
+ struct Glue<OptionSpec<k, Containers::Vector<T> > > : GlueBase
+ {
+ Glue (OptionSpec<k, Containers::Vector<T> > const& spec)
+ : parser_ (spec)
+ {
+ }
+
+ virtual Void
+ operator() (Char const* o, Scanner& scan, Void* options)
+ {
+ typedef typename Spec::Options Options;
+
+ Options& ops (*reinterpret_cast<Options*> (options));
+
+ ops.template value<k> ().push_back (parser_.parse (o, scan));
+ }
+
+ private:
+ OptionParser<OptionSpec<k, Containers::Vector<T> > > parser_;
+ };
+
+
+ // Option-specific specializations of some functions.
+ //
+ template <typename>
+ struct S_
+ {
+ // This is a "specialization" for when type is Bits::Null.
+ //
+ static Void
+ add_parser (Spec const&, Map&)
+ {
+ }
+
+ static Void
+ set_default (typename Spec::Options&, Spec const&)
+ {
+ }
+ };
+
+ template <Char const* k, typename T>
+ struct S_<OptionSpec<k, T> >
+ {
+ static Void
+ add_parser (Spec const& spec, Map& map)
+ {
+ if (k[0] != '\0')
+ {
+ OptionSpec<k, T> const& os (spec.template option<k> ());
+ map[os.name ()] = new Glue<OptionSpec<k, T> > (os);
+ }
+ }
+
+ static Void
+ set_default (typename Spec::Options& o, Spec const& s)
+ {
+ o.template value<k> () = s.template option<k> ().default_value ();
+ }
+ };
+
+ public:
+
+ OptionsParser (Spec const& spec)
+ : spec_ (spec)
+ {
+ S_<typename Spec::o01>::add_parser (spec_, map_);
+ S_<typename Spec::o02>::add_parser (spec_, map_);
+ S_<typename Spec::o03>::add_parser (spec_, map_);
+ S_<typename Spec::o04>::add_parser (spec_, map_);
+ S_<typename Spec::o05>::add_parser (spec_, map_);
+ S_<typename Spec::o06>::add_parser (spec_, map_);
+ S_<typename Spec::o07>::add_parser (spec_, map_);
+ S_<typename Spec::o08>::add_parser (spec_, map_);
+ S_<typename Spec::o09>::add_parser (spec_, map_);
+ S_<typename Spec::o10>::add_parser (spec_, map_);
+ S_<typename Spec::o11>::add_parser (spec_, map_);
+ S_<typename Spec::o12>::add_parser (spec_, map_);
+ S_<typename Spec::o13>::add_parser (spec_, map_);
+ S_<typename Spec::o14>::add_parser (spec_, map_);
+ S_<typename Spec::o15>::add_parser (spec_, map_);
+ S_<typename Spec::o16>::add_parser (spec_, map_);
+ S_<typename Spec::o17>::add_parser (spec_, map_);
+ S_<typename Spec::o18>::add_parser (spec_, map_);
+ S_<typename Spec::o19>::add_parser (spec_, map_);
+ S_<typename Spec::o20>::add_parser (spec_, map_);
+ S_<typename Spec::o21>::add_parser (spec_, map_);
+ S_<typename Spec::o22>::add_parser (spec_, map_);
+ S_<typename Spec::o23>::add_parser (spec_, map_);
+ S_<typename Spec::o24>::add_parser (spec_, map_);
+ S_<typename Spec::o25>::add_parser (spec_, map_);
+ S_<typename Spec::o26>::add_parser (spec_, map_);
+ S_<typename Spec::o27>::add_parser (spec_, map_);
+ S_<typename Spec::o28>::add_parser (spec_, map_);
+ S_<typename Spec::o29>::add_parser (spec_, map_);
+ S_<typename Spec::o30>::add_parser (spec_, map_);
+ S_<typename Spec::o31>::add_parser (spec_, map_);
+ S_<typename Spec::o32>::add_parser (spec_, map_);
+ S_<typename Spec::o33>::add_parser (spec_, map_);
+ S_<typename Spec::o34>::add_parser (spec_, map_);
+ S_<typename Spec::o35>::add_parser (spec_, map_);
+ S_<typename Spec::o36>::add_parser (spec_, map_);
+ S_<typename Spec::o37>::add_parser (spec_, map_);
+ S_<typename Spec::o38>::add_parser (spec_, map_);
+ S_<typename Spec::o39>::add_parser (spec_, map_);
+ S_<typename Spec::o40>::add_parser (spec_, map_);
+ S_<typename Spec::o41>::add_parser (spec_, map_);
+ S_<typename Spec::o42>::add_parser (spec_, map_);
+ S_<typename Spec::o43>::add_parser (spec_, map_);
+ S_<typename Spec::o44>::add_parser (spec_, map_);
+ S_<typename Spec::o45>::add_parser (spec_, map_);
+ S_<typename Spec::o46>::add_parser (spec_, map_);
+ S_<typename Spec::o47>::add_parser (spec_, map_);
+ S_<typename Spec::o48>::add_parser (spec_, map_);
+ S_<typename Spec::o49>::add_parser (spec_, map_);
+ S_<typename Spec::o50>::add_parser (spec_, map_);
+ S_<typename Spec::o51>::add_parser (spec_, map_);
+ S_<typename Spec::o52>::add_parser (spec_, map_);
+ S_<typename Spec::o53>::add_parser (spec_, map_);
+ S_<typename Spec::o54>::add_parser (spec_, map_);
+ S_<typename Spec::o55>::add_parser (spec_, map_);
+ S_<typename Spec::o56>::add_parser (spec_, map_);
+ S_<typename Spec::o57>::add_parser (spec_, map_);
+ S_<typename Spec::o58>::add_parser (spec_, map_);
+ S_<typename Spec::o59>::add_parser (spec_, map_);
+ S_<typename Spec::o60>::add_parser (spec_, map_);
+ S_<typename Spec::o61>::add_parser (spec_, map_);
+ S_<typename Spec::o62>::add_parser (spec_, map_);
+ S_<typename Spec::o63>::add_parser (spec_, map_);
+ S_<typename Spec::o64>::add_parser (spec_, map_);
+ S_<typename Spec::o65>::add_parser (spec_, map_);
+ S_<typename Spec::o66>::add_parser (spec_, map_);
+ S_<typename Spec::o67>::add_parser (spec_, map_);
+ S_<typename Spec::o68>::add_parser (spec_, map_);
+ S_<typename Spec::o69>::add_parser (spec_, map_);
+ S_<typename Spec::o70>::add_parser (spec_, map_);
+ S_<typename Spec::o71>::add_parser (spec_, map_);
+ S_<typename Spec::o72>::add_parser (spec_, map_);
+ S_<typename Spec::o73>::add_parser (spec_, map_);
+ S_<typename Spec::o74>::add_parser (spec_, map_);
+ S_<typename Spec::o75>::add_parser (spec_, map_);
+ S_<typename Spec::o76>::add_parser (spec_, map_);
+ S_<typename Spec::o77>::add_parser (spec_, map_);
+ S_<typename Spec::o78>::add_parser (spec_, map_);
+ S_<typename Spec::o79>::add_parser (spec_, map_);
+ S_<typename Spec::o80>::add_parser (spec_, map_);
+ S_<typename Spec::o81>::add_parser (spec_, map_);
+ S_<typename Spec::o82>::add_parser (spec_, map_);
+ S_<typename Spec::o83>::add_parser (spec_, map_);
+ S_<typename Spec::o84>::add_parser (spec_, map_);
+ S_<typename Spec::o85>::add_parser (spec_, map_);
+ S_<typename Spec::o86>::add_parser (spec_, map_);
+ S_<typename Spec::o87>::add_parser (spec_, map_);
+ S_<typename Spec::o88>::add_parser (spec_, map_);
+ S_<typename Spec::o89>::add_parser (spec_, map_);
+ S_<typename Spec::o90>::add_parser (spec_, map_);
+ S_<typename Spec::o91>::add_parser (spec_, map_);
+ S_<typename Spec::o92>::add_parser (spec_, map_);
+ S_<typename Spec::o93>::add_parser (spec_, map_);
+ S_<typename Spec::o94>::add_parser (spec_, map_);
+ S_<typename Spec::o95>::add_parser (spec_, map_);
+ S_<typename Spec::o96>::add_parser (spec_, map_);
+ S_<typename Spec::o97>::add_parser (spec_, map_);
+ S_<typename Spec::o98>::add_parser (spec_, map_);
+ S_<typename Spec::o99>::add_parser (spec_, map_);
+ S_<typename Spec::o100>::add_parser (spec_, map_);
+ }
+
+
+ typename Spec::Options
+ parse (Scanner& scan,
+ UnknownMode::Value option_mode = UnknownMode::fail,
+ UnknownMode::Value argument_mode = UnknownMode::stop)
+ {
+ typename Spec::Options ops;
+
+ S_<typename Spec::o01>::set_default (ops, spec_);
+ S_<typename Spec::o02>::set_default (ops, spec_);
+ S_<typename Spec::o03>::set_default (ops, spec_);
+ S_<typename Spec::o04>::set_default (ops, spec_);
+ S_<typename Spec::o05>::set_default (ops, spec_);
+ S_<typename Spec::o06>::set_default (ops, spec_);
+ S_<typename Spec::o07>::set_default (ops, spec_);
+ S_<typename Spec::o08>::set_default (ops, spec_);
+ S_<typename Spec::o09>::set_default (ops, spec_);
+ S_<typename Spec::o10>::set_default (ops, spec_);
+ S_<typename Spec::o11>::set_default (ops, spec_);
+ S_<typename Spec::o12>::set_default (ops, spec_);
+ S_<typename Spec::o13>::set_default (ops, spec_);
+ S_<typename Spec::o14>::set_default (ops, spec_);
+ S_<typename Spec::o15>::set_default (ops, spec_);
+ S_<typename Spec::o16>::set_default (ops, spec_);
+ S_<typename Spec::o17>::set_default (ops, spec_);
+ S_<typename Spec::o18>::set_default (ops, spec_);
+ S_<typename Spec::o19>::set_default (ops, spec_);
+ S_<typename Spec::o20>::set_default (ops, spec_);
+ S_<typename Spec::o21>::set_default (ops, spec_);
+ S_<typename Spec::o22>::set_default (ops, spec_);
+ S_<typename Spec::o23>::set_default (ops, spec_);
+ S_<typename Spec::o24>::set_default (ops, spec_);
+ S_<typename Spec::o25>::set_default (ops, spec_);
+ S_<typename Spec::o26>::set_default (ops, spec_);
+ S_<typename Spec::o27>::set_default (ops, spec_);
+ S_<typename Spec::o28>::set_default (ops, spec_);
+ S_<typename Spec::o29>::set_default (ops, spec_);
+ S_<typename Spec::o30>::set_default (ops, spec_);
+ S_<typename Spec::o31>::set_default (ops, spec_);
+ S_<typename Spec::o32>::set_default (ops, spec_);
+ S_<typename Spec::o33>::set_default (ops, spec_);
+ S_<typename Spec::o34>::set_default (ops, spec_);
+ S_<typename Spec::o35>::set_default (ops, spec_);
+ S_<typename Spec::o36>::set_default (ops, spec_);
+ S_<typename Spec::o37>::set_default (ops, spec_);
+ S_<typename Spec::o38>::set_default (ops, spec_);
+ S_<typename Spec::o39>::set_default (ops, spec_);
+ S_<typename Spec::o40>::set_default (ops, spec_);
+ S_<typename Spec::o41>::set_default (ops, spec_);
+ S_<typename Spec::o42>::set_default (ops, spec_);
+ S_<typename Spec::o43>::set_default (ops, spec_);
+ S_<typename Spec::o44>::set_default (ops, spec_);
+ S_<typename Spec::o45>::set_default (ops, spec_);
+ S_<typename Spec::o46>::set_default (ops, spec_);
+ S_<typename Spec::o47>::set_default (ops, spec_);
+ S_<typename Spec::o48>::set_default (ops, spec_);
+ S_<typename Spec::o49>::set_default (ops, spec_);
+ S_<typename Spec::o50>::set_default (ops, spec_);
+ S_<typename Spec::o51>::set_default (ops, spec_);
+ S_<typename Spec::o52>::set_default (ops, spec_);
+ S_<typename Spec::o53>::set_default (ops, spec_);
+ S_<typename Spec::o54>::set_default (ops, spec_);
+ S_<typename Spec::o55>::set_default (ops, spec_);
+ S_<typename Spec::o56>::set_default (ops, spec_);
+ S_<typename Spec::o57>::set_default (ops, spec_);
+ S_<typename Spec::o58>::set_default (ops, spec_);
+ S_<typename Spec::o59>::set_default (ops, spec_);
+ S_<typename Spec::o60>::set_default (ops, spec_);
+ S_<typename Spec::o61>::set_default (ops, spec_);
+ S_<typename Spec::o62>::set_default (ops, spec_);
+ S_<typename Spec::o63>::set_default (ops, spec_);
+ S_<typename Spec::o64>::set_default (ops, spec_);
+ S_<typename Spec::o65>::set_default (ops, spec_);
+ S_<typename Spec::o66>::set_default (ops, spec_);
+ S_<typename Spec::o67>::set_default (ops, spec_);
+ S_<typename Spec::o68>::set_default (ops, spec_);
+ S_<typename Spec::o69>::set_default (ops, spec_);
+ S_<typename Spec::o70>::set_default (ops, spec_);
+ S_<typename Spec::o71>::set_default (ops, spec_);
+ S_<typename Spec::o72>::set_default (ops, spec_);
+ S_<typename Spec::o73>::set_default (ops, spec_);
+ S_<typename Spec::o74>::set_default (ops, spec_);
+ S_<typename Spec::o75>::set_default (ops, spec_);
+ S_<typename Spec::o76>::set_default (ops, spec_);
+ S_<typename Spec::o77>::set_default (ops, spec_);
+ S_<typename Spec::o78>::set_default (ops, spec_);
+ S_<typename Spec::o79>::set_default (ops, spec_);
+ S_<typename Spec::o80>::set_default (ops, spec_);
+ S_<typename Spec::o81>::set_default (ops, spec_);
+ S_<typename Spec::o82>::set_default (ops, spec_);
+ S_<typename Spec::o83>::set_default (ops, spec_);
+ S_<typename Spec::o84>::set_default (ops, spec_);
+ S_<typename Spec::o85>::set_default (ops, spec_);
+ S_<typename Spec::o86>::set_default (ops, spec_);
+ S_<typename Spec::o87>::set_default (ops, spec_);
+ S_<typename Spec::o88>::set_default (ops, spec_);
+ S_<typename Spec::o89>::set_default (ops, spec_);
+ S_<typename Spec::o90>::set_default (ops, spec_);
+ S_<typename Spec::o91>::set_default (ops, spec_);
+ S_<typename Spec::o92>::set_default (ops, spec_);
+ S_<typename Spec::o93>::set_default (ops, spec_);
+ S_<typename Spec::o94>::set_default (ops, spec_);
+ S_<typename Spec::o95>::set_default (ops, spec_);
+ S_<typename Spec::o96>::set_default (ops, spec_);
+ S_<typename Spec::o97>::set_default (ops, spec_);
+ S_<typename Spec::o98>::set_default (ops, spec_);
+ S_<typename Spec::o99>::set_default (ops, spec_);
+ S_<typename Spec::o100>::set_default (ops, spec_);
+
+ for (Char const* s (scan.peek ()); s != Scanner::eos; s = scan.peek ())
+ {
+ tout << "looking at \"" << s << "\"";
+
+ //@@ Std::
+ //
+ if (strcmp (s, "--") == 0)
+ {
+ // We don't want to remove '--' if our option mode is skip.
+ //
+ if (option_mode == UnknownMode::skip)
+ scan.skip ();
+ else
+ scan.next ();
+
+ break;
+ }
+
+ typename Map::ConstIterator it (map_.find (s));
+
+ if (it != map_.end ())
+ {
+ tout << "found parser for \"" << s << "\"";
+
+ s = scan.next ();
+ (*(it->second)) (s, scan, &ops);
+ }
+ else if (s[0] == '-')
+ {
+ // Unknown option.
+ //
+ switch (option_mode)
+ {
+ case UnknownMode::skip:
+ {
+ scan.skip ();
+ continue;
+ }
+ case UnknownMode::stop:
+ {
+ break;
+ }
+ case UnknownMode::fail:
+ {
+ throw UnexpectedOption (s);
+ }
+ }
+
+ break; // stop case
+ }
+ else
+ {
+ // Something else.
+ //
+ switch (argument_mode)
+ {
+ case UnknownMode::skip:
+ {
+ scan.skip ();
+ continue;
+ }
+ case UnknownMode::stop:
+ {
+ break;
+ }
+ case UnknownMode::fail:
+ {
+ throw UnexpectedArgument (s);
+ }
+ }
+
+ break; // stop case
+ }
+ }
+
+ return ops;
+ }
+
+ private:
+ Map map_;
+ Spec spec_;
+ };
+
+ //
+ //
+ //
+
+ template <typename Spec>
+ typename Spec::Options
+ parse (Spec const& s,
+ Arguments& args,
+ UnknownMode::Value option_mode = UnknownMode::fail,
+ UnknownMode::Value argument_mode = UnknownMode::stop)
+ {
+ Scanner scan (args, Scanner::Action::erase);
+ OptionsParser<Spec> parser (s);
+
+ return parser.parse (scan, option_mode, argument_mode);
+ }
+
+ template <typename Options>
+ Options
+ parse (Arguments& args,
+ UnknownMode::Value option_mode = UnknownMode::fail,
+ UnknownMode::Value argument_mode = UnknownMode::stop)
+ {
+ OptionsSpec<Options> spec;
+ return parse (spec, args, option_mode, argument_mode);
+ }
+
+ template <typename Spec>
+ typename Spec::Options
+ parse (Spec const& s,
+ Int& argc,
+ Char** argv,
+ UnknownMode::Value option_mode = UnknownMode::fail,
+ UnknownMode::Value argument_mode = UnknownMode::stop)
+ {
+ BasicArguments args (argc, argv);
+ return parse (s, args, option_mode, argument_mode);
+ }
+
+ template <typename Options>
+ Options
+ parse (Int& argc,
+ Char** argv,
+ UnknownMode::Value option_mode = UnknownMode::fail,
+ UnknownMode::Value argument_mode = UnknownMode::stop)
+ {
+ OptionsSpec<Options> spec;
+
+ return parse (spec, argc, argv, option_mode, argument_mode);
+ }
+ }
+}
+
+#include <cult/cli/options-parser.ixx>
+#include <cult/cli/options-parser.txx>
+
+#endif // CULT_CLI_OPTIONS_PARSER_HXX
diff --git a/libcult/cult/cli/options-parser.ixx b/libcult/cult/cli/options-parser.ixx
new file mode 100644
index 0000000..80427f2
--- /dev/null
+++ b/libcult/cult/cli/options-parser.ixx
@@ -0,0 +1,12 @@
+// file : cult/cli/options-parser.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace CLI
+ {
+ }
+}
+
diff --git a/libcult/cult/cli/options-parser.txx b/libcult/cult/cli/options-parser.txx
new file mode 100644
index 0000000..bd8172a
--- /dev/null
+++ b/libcult/cult/cli/options-parser.txx
@@ -0,0 +1,34 @@
+// file : cult/cli/options-parser.txx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace CLI
+ {
+ // OptionParserBase
+ //
+ template <typename T>
+ T OptionParserBase<T>::
+ parse (Char const* o, Scanner& s)
+ {
+ Char const* v (s.next ());
+
+ //@@ "expected something after --option"?
+ //
+ if (v == Scanner::eos)
+ throw OptionFormat (o);
+
+ T r;
+ std::istringstream is (v);
+ is >> r;
+
+ if (is.fail () || !is.eof ())
+ throw OptionFormat (o);
+
+ return r;
+ }
+ }
+}
+
diff --git a/libcult/cult/cli/options-spec.cxx b/libcult/cult/cli/options-spec.cxx
new file mode 100644
index 0000000..9f1e43b
--- /dev/null
+++ b/libcult/cult/cli/options-spec.cxx
@@ -0,0 +1,14 @@
+// file : cult/cli/options-spec.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/cli/options-spec.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ }
+}
+
diff --git a/libcult/cult/cli/options-spec.hxx b/libcult/cult/cli/options-spec.hxx
new file mode 100644
index 0000000..aff4541
--- /dev/null
+++ b/libcult/cult/cli/options-spec.hxx
@@ -0,0 +1,723 @@
+// file : cult/cli/options-spec.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CLI_OPTIONS_SPEC_HXX
+#define CULT_CLI_OPTIONS_SPEC_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/cli/options.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ template <Char const* k, typename T>
+ class OptionSpec
+ {
+ public:
+ static Char const* const key;
+ typedef T Type;
+
+ public:
+ ~OptionSpec ()
+ {
+ }
+
+ OptionSpec ()
+ : default_value_ (),
+ name_ ("--")
+ {
+ name_ += k;
+ }
+
+ T const&
+ default_value () const
+ {
+ return default_value_;
+ }
+
+ Void
+ default_value (T const& value)
+ {
+ default_value_ = value;
+ }
+
+ //@@ bad name
+ //
+ Char const*
+ name () const
+ {
+ return name_.c_str ();
+ }
+
+ private:
+ T default_value_;
+ String name_;
+ };
+
+ template <Char const* k, typename T>
+ struct OptionSpecType
+ {
+ typedef OptionSpec<k, T> Type;
+ };
+
+ template <>
+ struct OptionSpecType<Bits::null, Bits::Null>
+ {
+ typedef Bits::Null Type;
+ };
+
+
+ template <Char const* k, typename T>
+ Char const* const OptionSpec<k, T>::key = k;
+
+ template <typename>
+ class OptionsSpec;
+
+ template <Char const* k01, typename T01,
+ Char const* k02, typename T02,
+ Char const* k03, typename T03,
+ Char const* k04, typename T04,
+ Char const* k05, typename T05,
+ Char const* k06, typename T06,
+ Char const* k07, typename T07,
+ Char const* k08, typename T08,
+ Char const* k09, typename T09,
+ Char const* k10, typename T10,
+ Char const* k11, typename T11,
+ Char const* k12, typename T12,
+ Char const* k13, typename T13,
+ Char const* k14, typename T14,
+ Char const* k15, typename T15,
+ Char const* k16, typename T16,
+ Char const* k17, typename T17,
+ Char const* k18, typename T18,
+ Char const* k19, typename T19,
+ Char const* k20, typename T20,
+ Char const* k21, typename T21,
+ Char const* k22, typename T22,
+ Char const* k23, typename T23,
+ Char const* k24, typename T24,
+ Char const* k25, typename T25,
+ Char const* k26, typename T26,
+ Char const* k27, typename T27,
+ Char const* k28, typename T28,
+ Char const* k29, typename T29,
+ Char const* k30, typename T30,
+ Char const* k31, typename T31,
+ Char const* k32, typename T32,
+ Char const* k33, typename T33,
+ Char const* k34, typename T34,
+ Char const* k35, typename T35,
+ Char const* k36, typename T36,
+ Char const* k37, typename T37,
+ Char const* k38, typename T38,
+ Char const* k39, typename T39,
+ Char const* k40, typename T40,
+ Char const* k41, typename T41,
+ Char const* k42, typename T42,
+ Char const* k43, typename T43,
+ Char const* k44, typename T44,
+ Char const* k45, typename T45,
+ Char const* k46, typename T46,
+ Char const* k47, typename T47,
+ Char const* k48, typename T48,
+ Char const* k49, typename T49,
+ Char const* k50, typename T50,
+ Char const* k51, typename T51,
+ Char const* k52, typename T52,
+ Char const* k53, typename T53,
+ Char const* k54, typename T54,
+ Char const* k55, typename T55,
+ Char const* k56, typename T56,
+ Char const* k57, typename T57,
+ Char const* k58, typename T58,
+ Char const* k59, typename T59,
+ Char const* k60, typename T60,
+ Char const* k61, typename T61,
+ Char const* k62, typename T62,
+ Char const* k63, typename T63,
+ Char const* k64, typename T64,
+ Char const* k65, typename T65,
+ Char const* k66, typename T66,
+ Char const* k67, typename T67,
+ Char const* k68, typename T68,
+ Char const* k69, typename T69,
+ Char const* k70, typename T70,
+ Char const* k71, typename T71,
+ Char const* k72, typename T72,
+ Char const* k73, typename T73,
+ Char const* k74, typename T74,
+ Char const* k75, typename T75,
+ Char const* k76, typename T76,
+ Char const* k77, typename T77,
+ Char const* k78, typename T78,
+ Char const* k79, typename T79,
+ Char const* k80, typename T80,
+ Char const* k81, typename T81,
+ Char const* k82, typename T82,
+ Char const* k83, typename T83,
+ Char const* k84, typename T84,
+ Char const* k85, typename T85,
+ Char const* k86, typename T86,
+ Char const* k87, typename T87,
+ Char const* k88, typename T88,
+ Char const* k89, typename T89,
+ Char const* k90, typename T90,
+ Char const* k91, typename T91,
+ Char const* k92, typename T92,
+ Char const* k93, typename T93,
+ Char const* k94, typename T94,
+ Char const* k95, typename T95,
+ Char const* k96, typename T96,
+ Char const* k97, typename T97,
+ Char const* k98, typename T98,
+ Char const* k99, typename T99,
+ Char const* k100, typename T100>
+
+ class OptionsSpec<Options<k01, T01,
+ k02, T02,
+ k03, T03,
+ k04, T04,
+ k05, T05,
+ k06, T06,
+ k07, T07,
+ k08, T08,
+ k09, T09,
+ k10, T10,
+ k11, T11,
+ k12, T12,
+ k13, T13,
+ k14, T14,
+ k15, T15,
+ k16, T16,
+ k17, T17,
+ k18, T18,
+ k19, T19,
+ k20, T20,
+ k21, T21,
+ k22, T22,
+ k23, T23,
+ k24, T24,
+ k25, T25,
+ k26, T26,
+ k27, T27,
+ k28, T28,
+ k29, T29,
+ k30, T30,
+ k31, T31,
+ k32, T32,
+ k33, T33,
+ k34, T34,
+ k35, T35,
+ k36, T36,
+ k37, T37,
+ k38, T38,
+ k39, T39,
+ k40, T40,
+ k41, T41,
+ k42, T42,
+ k43, T43,
+ k44, T44,
+ k45, T45,
+ k46, T46,
+ k47, T47,
+ k48, T48,
+ k49, T49,
+ k50, T50,
+ k51, T51,
+ k52, T52,
+ k53, T53,
+ k54, T54,
+ k55, T55,
+ k56, T56,
+ k57, T57,
+ k58, T58,
+ k59, T59,
+ k60, T60,
+ k61, T61,
+ k62, T62,
+ k63, T63,
+ k64, T64,
+ k65, T65,
+ k66, T66,
+ k67, T67,
+ k68, T68,
+ k69, T69,
+ k70, T70,
+ k71, T71,
+ k72, T72,
+ k73, T73,
+ k74, T74,
+ k75, T75,
+ k76, T76,
+ k77, T77,
+ k78, T78,
+ k79, T79,
+ k80, T80,
+ k81, T81,
+ k82, T82,
+ k83, T83,
+ k84, T84,
+ k85, T85,
+ k86, T86,
+ k87, T87,
+ k88, T88,
+ k89, T89,
+ k90, T90,
+ k91, T91,
+ k92, T92,
+ k93, T93,
+ k94, T94,
+ k95, T95,
+ k96, T96,
+ k97, T97,
+ k98, T98,
+ k99, T99,
+ k100, T100> >
+ {
+ public:
+ typedef CLI::Options<k01, T01,
+ k02, T02,
+ k03, T03,
+ k04, T04,
+ k05, T05,
+ k06, T06,
+ k07, T07,
+ k08, T08,
+ k09, T09,
+ k10, T10,
+ k11, T11,
+ k12, T12,
+ k13, T13,
+ k14, T14,
+ k15, T15,
+ k16, T16,
+ k17, T17,
+ k18, T18,
+ k19, T19,
+ k20, T20,
+ k21, T21,
+ k22, T22,
+ k23, T23,
+ k24, T24,
+ k25, T25,
+ k26, T26,
+ k27, T27,
+ k28, T28,
+ k29, T29,
+ k30, T30,
+ k31, T31,
+ k32, T32,
+ k33, T33,
+ k34, T34,
+ k35, T35,
+ k36, T36,
+ k37, T37,
+ k38, T38,
+ k39, T39,
+ k40, T40,
+ k41, T41,
+ k42, T42,
+ k43, T43,
+ k44, T44,
+ k45, T45,
+ k46, T46,
+ k47, T47,
+ k48, T48,
+ k49, T49,
+ k50, T50,
+ k51, T51,
+ k52, T52,
+ k53, T53,
+ k54, T54,
+ k55, T55,
+ k56, T56,
+ k57, T57,
+ k58, T58,
+ k59, T59,
+ k60, T60,
+ k61, T61,
+ k62, T62,
+ k63, T63,
+ k64, T64,
+ k65, T65,
+ k66, T66,
+ k67, T67,
+ k68, T68,
+ k69, T69,
+ k70, T70,
+ k71, T71,
+ k72, T72,
+ k73, T73,
+ k74, T74,
+ k75, T75,
+ k76, T76,
+ k77, T77,
+ k78, T78,
+ k79, T79,
+ k80, T80,
+ k81, T81,
+ k82, T82,
+ k83, T83,
+ k84, T84,
+ k85, T85,
+ k86, T86,
+ k87, T87,
+ k88, T88,
+ k89, T89,
+ k90, T90,
+ k91, T91,
+ k92, T92,
+ k93, T93,
+ k94, T94,
+ k95, T95,
+ k96, T96,
+ k97, T97,
+ k98, T98,
+ k99, T99,
+ k100, T100> Options;
+
+ typedef typename OptionSpecType<k01, T01>::Type o01;
+ typedef typename OptionSpecType<k02, T02>::Type o02;
+ typedef typename OptionSpecType<k03, T03>::Type o03;
+ typedef typename OptionSpecType<k04, T04>::Type o04;
+ typedef typename OptionSpecType<k05, T05>::Type o05;
+ typedef typename OptionSpecType<k06, T06>::Type o06;
+ typedef typename OptionSpecType<k07, T07>::Type o07;
+ typedef typename OptionSpecType<k08, T08>::Type o08;
+ typedef typename OptionSpecType<k09, T09>::Type o09;
+ typedef typename OptionSpecType<k10, T10>::Type o10;
+ typedef typename OptionSpecType<k11, T11>::Type o11;
+ typedef typename OptionSpecType<k12, T12>::Type o12;
+ typedef typename OptionSpecType<k13, T13>::Type o13;
+ typedef typename OptionSpecType<k14, T14>::Type o14;
+ typedef typename OptionSpecType<k15, T15>::Type o15;
+ typedef typename OptionSpecType<k16, T16>::Type o16;
+ typedef typename OptionSpecType<k17, T17>::Type o17;
+ typedef typename OptionSpecType<k18, T18>::Type o18;
+ typedef typename OptionSpecType<k19, T19>::Type o19;
+ typedef typename OptionSpecType<k20, T20>::Type o20;
+ typedef typename OptionSpecType<k21, T21>::Type o21;
+ typedef typename OptionSpecType<k22, T22>::Type o22;
+ typedef typename OptionSpecType<k23, T23>::Type o23;
+ typedef typename OptionSpecType<k24, T24>::Type o24;
+ typedef typename OptionSpecType<k25, T25>::Type o25;
+ typedef typename OptionSpecType<k26, T26>::Type o26;
+ typedef typename OptionSpecType<k27, T27>::Type o27;
+ typedef typename OptionSpecType<k28, T28>::Type o28;
+ typedef typename OptionSpecType<k29, T29>::Type o29;
+ typedef typename OptionSpecType<k30, T30>::Type o30;
+ typedef typename OptionSpecType<k31, T31>::Type o31;
+ typedef typename OptionSpecType<k32, T32>::Type o32;
+ typedef typename OptionSpecType<k33, T33>::Type o33;
+ typedef typename OptionSpecType<k34, T34>::Type o34;
+ typedef typename OptionSpecType<k35, T35>::Type o35;
+ typedef typename OptionSpecType<k36, T36>::Type o36;
+ typedef typename OptionSpecType<k37, T37>::Type o37;
+ typedef typename OptionSpecType<k38, T38>::Type o38;
+ typedef typename OptionSpecType<k39, T39>::Type o39;
+ typedef typename OptionSpecType<k40, T40>::Type o40;
+ typedef typename OptionSpecType<k41, T41>::Type o41;
+ typedef typename OptionSpecType<k42, T42>::Type o42;
+ typedef typename OptionSpecType<k43, T43>::Type o43;
+ typedef typename OptionSpecType<k44, T44>::Type o44;
+ typedef typename OptionSpecType<k45, T45>::Type o45;
+ typedef typename OptionSpecType<k46, T46>::Type o46;
+ typedef typename OptionSpecType<k47, T47>::Type o47;
+ typedef typename OptionSpecType<k48, T48>::Type o48;
+ typedef typename OptionSpecType<k49, T49>::Type o49;
+ typedef typename OptionSpecType<k50, T50>::Type o50;
+ typedef typename OptionSpecType<k51, T51>::Type o51;
+ typedef typename OptionSpecType<k52, T52>::Type o52;
+ typedef typename OptionSpecType<k53, T53>::Type o53;
+ typedef typename OptionSpecType<k54, T54>::Type o54;
+ typedef typename OptionSpecType<k55, T55>::Type o55;
+ typedef typename OptionSpecType<k56, T56>::Type o56;
+ typedef typename OptionSpecType<k57, T57>::Type o57;
+ typedef typename OptionSpecType<k58, T58>::Type o58;
+ typedef typename OptionSpecType<k59, T59>::Type o59;
+ typedef typename OptionSpecType<k60, T60>::Type o60;
+ typedef typename OptionSpecType<k61, T61>::Type o61;
+ typedef typename OptionSpecType<k62, T62>::Type o62;
+ typedef typename OptionSpecType<k63, T63>::Type o63;
+ typedef typename OptionSpecType<k64, T64>::Type o64;
+ typedef typename OptionSpecType<k65, T65>::Type o65;
+ typedef typename OptionSpecType<k66, T66>::Type o66;
+ typedef typename OptionSpecType<k67, T67>::Type o67;
+ typedef typename OptionSpecType<k68, T68>::Type o68;
+ typedef typename OptionSpecType<k69, T69>::Type o69;
+ typedef typename OptionSpecType<k70, T70>::Type o70;
+ typedef typename OptionSpecType<k71, T71>::Type o71;
+ typedef typename OptionSpecType<k72, T72>::Type o72;
+ typedef typename OptionSpecType<k73, T73>::Type o73;
+ typedef typename OptionSpecType<k74, T74>::Type o74;
+ typedef typename OptionSpecType<k75, T75>::Type o75;
+ typedef typename OptionSpecType<k76, T76>::Type o76;
+ typedef typename OptionSpecType<k77, T77>::Type o77;
+ typedef typename OptionSpecType<k78, T78>::Type o78;
+ typedef typename OptionSpecType<k79, T79>::Type o79;
+ typedef typename OptionSpecType<k80, T80>::Type o80;
+ typedef typename OptionSpecType<k81, T81>::Type o81;
+ typedef typename OptionSpecType<k82, T82>::Type o82;
+ typedef typename OptionSpecType<k83, T83>::Type o83;
+ typedef typename OptionSpecType<k84, T84>::Type o84;
+ typedef typename OptionSpecType<k85, T85>::Type o85;
+ typedef typename OptionSpecType<k86, T86>::Type o86;
+ typedef typename OptionSpecType<k87, T87>::Type o87;
+ typedef typename OptionSpecType<k88, T88>::Type o88;
+ typedef typename OptionSpecType<k89, T89>::Type o89;
+ typedef typename OptionSpecType<k90, T90>::Type o90;
+ typedef typename OptionSpecType<k91, T91>::Type o91;
+ typedef typename OptionSpecType<k92, T92>::Type o92;
+ typedef typename OptionSpecType<k93, T93>::Type o93;
+ typedef typename OptionSpecType<k94, T94>::Type o94;
+ typedef typename OptionSpecType<k95, T95>::Type o95;
+ typedef typename OptionSpecType<k96, T96>::Type o96;
+ typedef typename OptionSpecType<k97, T97>::Type o97;
+ typedef typename OptionSpecType<k98, T98>::Type o98;
+ typedef typename OptionSpecType<k99, T99>::Type o99;
+ typedef typename OptionSpecType<k100, T100>::Type o100;
+
+
+ private:
+ typedef Bits::Mapper<k01, o01,
+ k02, o02,
+ k03, o03,
+ k04, o04,
+ k05, o05,
+ k06, o06,
+ k07, o07,
+ k08, o08,
+ k09, o09,
+ k10, o10,
+ k11, o11,
+ k12, o12,
+ k13, o13,
+ k14, o14,
+ k15, o15,
+ k16, o16,
+ k17, o17,
+ k18, o18,
+ k19, o19,
+ k20, o20,
+ k21, o21,
+ k22, o22,
+ k23, o23,
+ k24, o24,
+ k25, o25,
+ k26, o26,
+ k27, o27,
+ k28, o28,
+ k29, o29,
+ k30, o30,
+ k31, o31,
+ k32, o32,
+ k33, o33,
+ k34, o34,
+ k35, o35,
+ k36, o36,
+ k37, o37,
+ k38, o38,
+ k39, o39,
+ k40, o40,
+ k41, o41,
+ k42, o42,
+ k43, o43,
+ k44, o44,
+ k45, o45,
+ k46, o46,
+ k47, o47,
+ k48, o48,
+ k49, o49,
+ k50, o50,
+ k51, o51,
+ k52, o52,
+ k53, o53,
+ k54, o54,
+ k55, o55,
+ k56, o56,
+ k57, o57,
+ k58, o58,
+ k59, o59,
+ k60, o60,
+ k61, o61,
+ k62, o62,
+ k63, o63,
+ k64, o64,
+ k65, o65,
+ k66, o66,
+ k67, o67,
+ k68, o68,
+ k69, o69,
+ k70, o70,
+ k71, o71,
+ k72, o72,
+ k73, o73,
+ k74, o74,
+ k75, o75,
+ k76, o76,
+ k77, o77,
+ k78, o78,
+ k79, o79,
+ k80, o80,
+ k81, o81,
+ k82, o82,
+ k83, o83,
+ k84, o84,
+ k85, o85,
+ k86, o86,
+ k87, o87,
+ k88, o88,
+ k89, o89,
+ k90, o90,
+ k91, o91,
+ k92, o92,
+ k93, o93,
+ k94, o94,
+ k95, o95,
+ k96, o96,
+ k97, o97,
+ k98, o98,
+ k99, o99,
+ k100, o100> Mapper;
+
+ public:
+ template <Char const* k>
+ typename Mapper::template Selector<k>::Type&
+ option ()
+ {
+ typedef
+ typename Mapper::template Selector<k>::Type
+ Type;
+
+ return *reinterpret_cast<Type*> (option (k));
+ }
+
+ template <Char const* k>
+ typename Mapper::template Selector<k>::Type const&
+ option () const
+ {
+ typedef
+ typename Mapper::template Selector<k>::Type
+ Type;
+
+ return *reinterpret_cast<Type const*> (option (k));
+ }
+
+ private:
+ Void*
+ option (Char const*) const;
+
+ private:
+ o01 o01_;
+ o02 o02_;
+ o03 o03_;
+ o04 o04_;
+ o05 o05_;
+ o06 o06_;
+ o07 o07_;
+ o08 o08_;
+ o09 o09_;
+ o10 o10_;
+ o11 o11_;
+ o12 o12_;
+ o13 o13_;
+ o14 o14_;
+ o15 o15_;
+ o16 o16_;
+ o17 o17_;
+ o18 o18_;
+ o19 o19_;
+ o20 o20_;
+ o21 o21_;
+ o22 o22_;
+ o23 o23_;
+ o24 o24_;
+ o25 o25_;
+ o26 o26_;
+ o27 o27_;
+ o28 o28_;
+ o29 o29_;
+ o30 o30_;
+ o31 o31_;
+ o32 o32_;
+ o33 o33_;
+ o34 o34_;
+ o35 o35_;
+ o36 o36_;
+ o37 o37_;
+ o38 o38_;
+ o39 o39_;
+ o40 o40_;
+ o41 o41_;
+ o42 o42_;
+ o43 o43_;
+ o44 o44_;
+ o45 o45_;
+ o46 o46_;
+ o47 o47_;
+ o48 o48_;
+ o49 o49_;
+ o50 o50_;
+ o51 o51_;
+ o52 o52_;
+ o53 o53_;
+ o54 o54_;
+ o55 o55_;
+ o56 o56_;
+ o57 o57_;
+ o58 o58_;
+ o59 o59_;
+ o60 o60_;
+ o61 o61_;
+ o62 o62_;
+ o63 o63_;
+ o64 o64_;
+ o65 o65_;
+ o66 o66_;
+ o67 o67_;
+ o68 o68_;
+ o69 o69_;
+ o70 o70_;
+ o71 o71_;
+ o72 o72_;
+ o73 o73_;
+ o74 o74_;
+ o75 o75_;
+ o76 o76_;
+ o77 o77_;
+ o78 o78_;
+ o79 o79_;
+ o80 o80_;
+ o81 o81_;
+ o82 o82_;
+ o83 o83_;
+ o84 o84_;
+ o85 o85_;
+ o86 o86_;
+ o87 o87_;
+ o88 o88_;
+ o89 o89_;
+ o90 o90_;
+ o91 o91_;
+ o92 o92_;
+ o93 o93_;
+ o94 o94_;
+ o95 o95_;
+ o96 o96_;
+ o97 o97_;
+ o98 o98_;
+ o99 o99_;
+ o100 o100_;
+ };
+ }
+}
+
+#include <cult/cli/options-spec.ixx>
+#include <cult/cli/options-spec.txx>
+
+#endif // CULT_CLI_OPTIONS_SPEC_HXX
diff --git a/libcult/cult/cli/options-spec.ixx b/libcult/cult/cli/options-spec.ixx
new file mode 100644
index 0000000..1c47da1
--- /dev/null
+++ b/libcult/cult/cli/options-spec.ixx
@@ -0,0 +1,12 @@
+// file : cult/cli/options-spec.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace CLI
+ {
+ }
+}
+
diff --git a/libcult/cult/cli/options-spec.txx b/libcult/cult/cli/options-spec.txx
new file mode 100644
index 0000000..f5d59a0
--- /dev/null
+++ b/libcult/cult/cli/options-spec.txx
@@ -0,0 +1,320 @@
+// file : cult/cli/options-spec.txx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace CLI
+ {
+ template <Char const* k01, typename T01,
+ Char const* k02, typename T02,
+ Char const* k03, typename T03,
+ Char const* k04, typename T04,
+ Char const* k05, typename T05,
+ Char const* k06, typename T06,
+ Char const* k07, typename T07,
+ Char const* k08, typename T08,
+ Char const* k09, typename T09,
+ Char const* k10, typename T10,
+ Char const* k11, typename T11,
+ Char const* k12, typename T12,
+ Char const* k13, typename T13,
+ Char const* k14, typename T14,
+ Char const* k15, typename T15,
+ Char const* k16, typename T16,
+ Char const* k17, typename T17,
+ Char const* k18, typename T18,
+ Char const* k19, typename T19,
+ Char const* k20, typename T20,
+ Char const* k21, typename T21,
+ Char const* k22, typename T22,
+ Char const* k23, typename T23,
+ Char const* k24, typename T24,
+ Char const* k25, typename T25,
+ Char const* k26, typename T26,
+ Char const* k27, typename T27,
+ Char const* k28, typename T28,
+ Char const* k29, typename T29,
+ Char const* k30, typename T30,
+ Char const* k31, typename T31,
+ Char const* k32, typename T32,
+ Char const* k33, typename T33,
+ Char const* k34, typename T34,
+ Char const* k35, typename T35,
+ Char const* k36, typename T36,
+ Char const* k37, typename T37,
+ Char const* k38, typename T38,
+ Char const* k39, typename T39,
+ Char const* k40, typename T40,
+ Char const* k41, typename T41,
+ Char const* k42, typename T42,
+ Char const* k43, typename T43,
+ Char const* k44, typename T44,
+ Char const* k45, typename T45,
+ Char const* k46, typename T46,
+ Char const* k47, typename T47,
+ Char const* k48, typename T48,
+ Char const* k49, typename T49,
+ Char const* k50, typename T50,
+ Char const* k51, typename T51,
+ Char const* k52, typename T52,
+ Char const* k53, typename T53,
+ Char const* k54, typename T54,
+ Char const* k55, typename T55,
+ Char const* k56, typename T56,
+ Char const* k57, typename T57,
+ Char const* k58, typename T58,
+ Char const* k59, typename T59,
+ Char const* k60, typename T60,
+ Char const* k61, typename T61,
+ Char const* k62, typename T62,
+ Char const* k63, typename T63,
+ Char const* k64, typename T64,
+ Char const* k65, typename T65,
+ Char const* k66, typename T66,
+ Char const* k67, typename T67,
+ Char const* k68, typename T68,
+ Char const* k69, typename T69,
+ Char const* k70, typename T70,
+ Char const* k71, typename T71,
+ Char const* k72, typename T72,
+ Char const* k73, typename T73,
+ Char const* k74, typename T74,
+ Char const* k75, typename T75,
+ Char const* k76, typename T76,
+ Char const* k77, typename T77,
+ Char const* k78, typename T78,
+ Char const* k79, typename T79,
+ Char const* k80, typename T80,
+ Char const* k81, typename T81,
+ Char const* k82, typename T82,
+ Char const* k83, typename T83,
+ Char const* k84, typename T84,
+ Char const* k85, typename T85,
+ Char const* k86, typename T86,
+ Char const* k87, typename T87,
+ Char const* k88, typename T88,
+ Char const* k89, typename T89,
+ Char const* k90, typename T90,
+ Char const* k91, typename T91,
+ Char const* k92, typename T92,
+ Char const* k93, typename T93,
+ Char const* k94, typename T94,
+ Char const* k95, typename T95,
+ Char const* k96, typename T96,
+ Char const* k97, typename T97,
+ Char const* k98, typename T98,
+ Char const* k99, typename T99,
+ Char const* k100, typename T100>
+ Void*
+ OptionsSpec<Options<k01, T01,
+ k02, T02,
+ k03, T03,
+ k04, T04,
+ k05, T05,
+ k06, T06,
+ k07, T07,
+ k08, T08,
+ k09, T09,
+ k10, T10,
+ k11, T11,
+ k12, T12,
+ k13, T13,
+ k14, T14,
+ k15, T15,
+ k16, T16,
+ k17, T17,
+ k18, T18,
+ k19, T19,
+ k20, T20,
+ k21, T21,
+ k22, T22,
+ k23, T23,
+ k24, T24,
+ k25, T25,
+ k26, T26,
+ k27, T27,
+ k28, T28,
+ k29, T29,
+ k30, T30,
+ k31, T31,
+ k32, T32,
+ k33, T33,
+ k34, T34,
+ k35, T35,
+ k36, T36,
+ k37, T37,
+ k38, T38,
+ k39, T39,
+ k40, T40,
+ k41, T41,
+ k42, T42,
+ k43, T43,
+ k44, T44,
+ k45, T45,
+ k46, T46,
+ k47, T47,
+ k48, T48,
+ k49, T49,
+ k50, T50,
+ k51, T51,
+ k52, T52,
+ k53, T53,
+ k54, T54,
+ k55, T55,
+ k56, T56,
+ k57, T57,
+ k58, T58,
+ k59, T59,
+ k60, T60,
+ k61, T61,
+ k62, T62,
+ k63, T63,
+ k64, T64,
+ k65, T65,
+ k66, T66,
+ k67, T67,
+ k68, T68,
+ k69, T69,
+ k70, T70,
+ k71, T71,
+ k72, T72,
+ k73, T73,
+ k74, T74,
+ k75, T75,
+ k76, T76,
+ k77, T77,
+ k78, T78,
+ k79, T79,
+ k80, T80,
+ k81, T81,
+ k82, T82,
+ k83, T83,
+ k84, T84,
+ k85, T85,
+ k86, T86,
+ k87, T87,
+ k88, T88,
+ k89, T89,
+ k90, T90,
+ k91, T91,
+ k92, T92,
+ k93, T93,
+ k94, T94,
+ k95, T95,
+ k96, T96,
+ k97, T97,
+ k98, T98,
+ k99, T99,
+ k100, T100> >::
+ option (Char const* k) const
+ {
+ Void* r (0);
+
+ if (k == k01) r = (Void*) (&o01_); else
+ if (k == k02) r = (Void*) (&o02_); else
+ if (k == k03) r = (Void*) (&o03_); else
+ if (k == k04) r = (Void*) (&o04_); else
+ if (k == k05) r = (Void*) (&o05_); else
+ if (k == k06) r = (Void*) (&o06_); else
+ if (k == k07) r = (Void*) (&o07_); else
+ if (k == k08) r = (Void*) (&o08_); else
+ if (k == k09) r = (Void*) (&o09_); else
+ if (k == k10) r = (Void*) (&o10_); else
+ if (k == k11) r = (Void*) (&o11_); else
+ if (k == k12) r = (Void*) (&o12_); else
+ if (k == k13) r = (Void*) (&o13_); else
+ if (k == k14) r = (Void*) (&o14_); else
+ if (k == k15) r = (Void*) (&o15_); else
+ if (k == k16) r = (Void*) (&o16_); else
+ if (k == k17) r = (Void*) (&o17_); else
+ if (k == k18) r = (Void*) (&o18_); else
+ if (k == k19) r = (Void*) (&o19_); else
+ if (k == k20) r = (Void*) (&o20_); else
+ if (k == k21) r = (Void*) (&o21_); else
+ if (k == k22) r = (Void*) (&o22_); else
+ if (k == k23) r = (Void*) (&o23_); else
+ if (k == k24) r = (Void*) (&o24_); else
+ if (k == k25) r = (Void*) (&o25_); else
+ if (k == k26) r = (Void*) (&o26_); else
+ if (k == k27) r = (Void*) (&o27_); else
+ if (k == k28) r = (Void*) (&o28_); else
+ if (k == k29) r = (Void*) (&o29_); else
+ if (k == k30) r = (Void*) (&o30_); else
+ if (k == k31) r = (Void*) (&o31_); else
+ if (k == k32) r = (Void*) (&o32_); else
+ if (k == k33) r = (Void*) (&o33_); else
+ if (k == k34) r = (Void*) (&o34_); else
+ if (k == k35) r = (Void*) (&o35_); else
+ if (k == k36) r = (Void*) (&o36_); else
+ if (k == k37) r = (Void*) (&o37_); else
+ if (k == k38) r = (Void*) (&o38_); else
+ if (k == k39) r = (Void*) (&o39_); else
+ if (k == k40) r = (Void*) (&o40_); else
+ if (k == k41) r = (Void*) (&o41_); else
+ if (k == k42) r = (Void*) (&o42_); else
+ if (k == k43) r = (Void*) (&o43_); else
+ if (k == k44) r = (Void*) (&o44_); else
+ if (k == k45) r = (Void*) (&o45_); else
+ if (k == k46) r = (Void*) (&o46_); else
+ if (k == k47) r = (Void*) (&o47_); else
+ if (k == k48) r = (Void*) (&o48_); else
+ if (k == k49) r = (Void*) (&o49_); else
+ if (k == k50) r = (Void*) (&o50_); else
+ if (k == k51) r = (Void*) (&o51_); else
+ if (k == k52) r = (Void*) (&o52_); else
+ if (k == k53) r = (Void*) (&o53_); else
+ if (k == k54) r = (Void*) (&o54_); else
+ if (k == k55) r = (Void*) (&o55_); else
+ if (k == k56) r = (Void*) (&o56_); else
+ if (k == k57) r = (Void*) (&o57_); else
+ if (k == k58) r = (Void*) (&o58_); else
+ if (k == k59) r = (Void*) (&o59_); else
+ if (k == k60) r = (Void*) (&o60_); else
+ if (k == k61) r = (Void*) (&o61_); else
+ if (k == k62) r = (Void*) (&o62_); else
+ if (k == k63) r = (Void*) (&o63_); else
+ if (k == k64) r = (Void*) (&o64_); else
+ if (k == k65) r = (Void*) (&o65_); else
+ if (k == k66) r = (Void*) (&o66_); else
+ if (k == k67) r = (Void*) (&o67_); else
+ if (k == k68) r = (Void*) (&o68_); else
+ if (k == k69) r = (Void*) (&o69_); else
+ if (k == k70) r = (Void*) (&o70_); else
+ if (k == k71) r = (Void*) (&o71_); else
+ if (k == k72) r = (Void*) (&o72_); else
+ if (k == k73) r = (Void*) (&o73_); else
+ if (k == k74) r = (Void*) (&o74_); else
+ if (k == k75) r = (Void*) (&o75_); else
+ if (k == k76) r = (Void*) (&o76_); else
+ if (k == k77) r = (Void*) (&o77_); else
+ if (k == k78) r = (Void*) (&o78_); else
+ if (k == k79) r = (Void*) (&o79_); else
+ if (k == k80) r = (Void*) (&o80_); else
+ if (k == k81) r = (Void*) (&o81_); else
+ if (k == k82) r = (Void*) (&o82_); else
+ if (k == k83) r = (Void*) (&o83_); else
+ if (k == k84) r = (Void*) (&o84_); else
+ if (k == k85) r = (Void*) (&o85_); else
+ if (k == k86) r = (Void*) (&o86_); else
+ if (k == k87) r = (Void*) (&o87_); else
+ if (k == k88) r = (Void*) (&o88_); else
+ if (k == k89) r = (Void*) (&o89_); else
+ if (k == k90) r = (Void*) (&o90_); else
+ if (k == k91) r = (Void*) (&o91_); else
+ if (k == k92) r = (Void*) (&o92_); else
+ if (k == k93) r = (Void*) (&o93_); else
+ if (k == k94) r = (Void*) (&o94_); else
+ if (k == k95) r = (Void*) (&o95_); else
+ if (k == k96) r = (Void*) (&o96_); else
+ if (k == k97) r = (Void*) (&o97_); else
+ if (k == k98) r = (Void*) (&o98_); else
+ if (k == k99) r = (Void*) (&o99_); else
+ if (k == k100) r = (Void*) (&o100_); else
+ assert (false);
+
+ return r;
+ }
+ }
+}
diff --git a/libcult/cult/cli/options.cxx b/libcult/cult/cli/options.cxx
new file mode 100644
index 0000000..6b6e996
--- /dev/null
+++ b/libcult/cult/cli/options.cxx
@@ -0,0 +1,17 @@
+// file : cult/cli/options.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/cli/options.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ namespace Bits
+ {
+ extern Char const null[] = "";
+ }
+ }
+}
diff --git a/libcult/cult/cli/options.hxx b/libcult/cult/cli/options.hxx
new file mode 100644
index 0000000..2a780e1
--- /dev/null
+++ b/libcult/cult/cli/options.hxx
@@ -0,0 +1,502 @@
+// file : cult/cli/options.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CLI_OPTIONS_HXX
+#define CULT_CLI_OPTIONS_HXX
+
+#include <cult/types.hxx>
+
+#include <cassert>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ namespace Bits
+ {
+ template <Boolean t, typename X, typename Y>
+ struct if_;
+
+ template <typename X, typename Y>
+ struct if_<true, X, Y>
+ {
+ typedef X Type;
+ };
+
+ template <typename X, typename Y>
+ struct if_<false, X, Y>
+ {
+ typedef Y Type;
+ };
+
+ template <Char const* x, Char const* y>
+ struct same
+ {
+ static Boolean const r = false;
+ };
+
+ template <Char const* x>
+ struct same<x, x>
+ {
+ static Boolean const r = true;
+ };
+
+ template <Char const* x>
+ struct Tag
+ {
+ };
+
+ //@@ should end up in Cult::Meta
+ //
+ struct Null {};
+ extern Char const null[];
+
+#include <cult/cli/mapper.hxx>
+
+ }
+
+ template <Char const* k01, typename T01,
+ Char const* k02 = Bits::null, typename T02 = Bits::Null,
+ Char const* k03 = Bits::null, typename T03 = Bits::Null,
+ Char const* k04 = Bits::null, typename T04 = Bits::Null,
+ Char const* k05 = Bits::null, typename T05 = Bits::Null,
+ Char const* k06 = Bits::null, typename T06 = Bits::Null,
+ Char const* k07 = Bits::null, typename T07 = Bits::Null,
+ Char const* k08 = Bits::null, typename T08 = Bits::Null,
+ Char const* k09 = Bits::null, typename T09 = Bits::Null,
+ Char const* k10 = Bits::null, typename T10 = Bits::Null,
+ Char const* k11 = Bits::null, typename T11 = Bits::Null,
+ Char const* k12 = Bits::null, typename T12 = Bits::Null,
+ Char const* k13 = Bits::null, typename T13 = Bits::Null,
+ Char const* k14 = Bits::null, typename T14 = Bits::Null,
+ Char const* k15 = Bits::null, typename T15 = Bits::Null,
+ Char const* k16 = Bits::null, typename T16 = Bits::Null,
+ Char const* k17 = Bits::null, typename T17 = Bits::Null,
+ Char const* k18 = Bits::null, typename T18 = Bits::Null,
+ Char const* k19 = Bits::null, typename T19 = Bits::Null,
+ Char const* k20 = Bits::null, typename T20 = Bits::Null,
+ Char const* k21 = Bits::null, typename T21 = Bits::Null,
+ Char const* k22 = Bits::null, typename T22 = Bits::Null,
+ Char const* k23 = Bits::null, typename T23 = Bits::Null,
+ Char const* k24 = Bits::null, typename T24 = Bits::Null,
+ Char const* k25 = Bits::null, typename T25 = Bits::Null,
+ Char const* k26 = Bits::null, typename T26 = Bits::Null,
+ Char const* k27 = Bits::null, typename T27 = Bits::Null,
+ Char const* k28 = Bits::null, typename T28 = Bits::Null,
+ Char const* k29 = Bits::null, typename T29 = Bits::Null,
+ Char const* k30 = Bits::null, typename T30 = Bits::Null,
+ Char const* k31 = Bits::null, typename T31 = Bits::Null,
+ Char const* k32 = Bits::null, typename T32 = Bits::Null,
+ Char const* k33 = Bits::null, typename T33 = Bits::Null,
+ Char const* k34 = Bits::null, typename T34 = Bits::Null,
+ Char const* k35 = Bits::null, typename T35 = Bits::Null,
+ Char const* k36 = Bits::null, typename T36 = Bits::Null,
+ Char const* k37 = Bits::null, typename T37 = Bits::Null,
+ Char const* k38 = Bits::null, typename T38 = Bits::Null,
+ Char const* k39 = Bits::null, typename T39 = Bits::Null,
+ Char const* k40 = Bits::null, typename T40 = Bits::Null,
+ Char const* k41 = Bits::null, typename T41 = Bits::Null,
+ Char const* k42 = Bits::null, typename T42 = Bits::Null,
+ Char const* k43 = Bits::null, typename T43 = Bits::Null,
+ Char const* k44 = Bits::null, typename T44 = Bits::Null,
+ Char const* k45 = Bits::null, typename T45 = Bits::Null,
+ Char const* k46 = Bits::null, typename T46 = Bits::Null,
+ Char const* k47 = Bits::null, typename T47 = Bits::Null,
+ Char const* k48 = Bits::null, typename T48 = Bits::Null,
+ Char const* k49 = Bits::null, typename T49 = Bits::Null,
+ Char const* k50 = Bits::null, typename T50 = Bits::Null,
+ Char const* k51 = Bits::null, typename T51 = Bits::Null,
+ Char const* k52 = Bits::null, typename T52 = Bits::Null,
+ Char const* k53 = Bits::null, typename T53 = Bits::Null,
+ Char const* k54 = Bits::null, typename T54 = Bits::Null,
+ Char const* k55 = Bits::null, typename T55 = Bits::Null,
+ Char const* k56 = Bits::null, typename T56 = Bits::Null,
+ Char const* k57 = Bits::null, typename T57 = Bits::Null,
+ Char const* k58 = Bits::null, typename T58 = Bits::Null,
+ Char const* k59 = Bits::null, typename T59 = Bits::Null,
+ Char const* k60 = Bits::null, typename T60 = Bits::Null,
+ Char const* k61 = Bits::null, typename T61 = Bits::Null,
+ Char const* k62 = Bits::null, typename T62 = Bits::Null,
+ Char const* k63 = Bits::null, typename T63 = Bits::Null,
+ Char const* k64 = Bits::null, typename T64 = Bits::Null,
+ Char const* k65 = Bits::null, typename T65 = Bits::Null,
+ Char const* k66 = Bits::null, typename T66 = Bits::Null,
+ Char const* k67 = Bits::null, typename T67 = Bits::Null,
+ Char const* k68 = Bits::null, typename T68 = Bits::Null,
+ Char const* k69 = Bits::null, typename T69 = Bits::Null,
+ Char const* k70 = Bits::null, typename T70 = Bits::Null,
+ Char const* k71 = Bits::null, typename T71 = Bits::Null,
+ Char const* k72 = Bits::null, typename T72 = Bits::Null,
+ Char const* k73 = Bits::null, typename T73 = Bits::Null,
+ Char const* k74 = Bits::null, typename T74 = Bits::Null,
+ Char const* k75 = Bits::null, typename T75 = Bits::Null,
+ Char const* k76 = Bits::null, typename T76 = Bits::Null,
+ Char const* k77 = Bits::null, typename T77 = Bits::Null,
+ Char const* k78 = Bits::null, typename T78 = Bits::Null,
+ Char const* k79 = Bits::null, typename T79 = Bits::Null,
+ Char const* k80 = Bits::null, typename T80 = Bits::Null,
+ Char const* k81 = Bits::null, typename T81 = Bits::Null,
+ Char const* k82 = Bits::null, typename T82 = Bits::Null,
+ Char const* k83 = Bits::null, typename T83 = Bits::Null,
+ Char const* k84 = Bits::null, typename T84 = Bits::Null,
+ Char const* k85 = Bits::null, typename T85 = Bits::Null,
+ Char const* k86 = Bits::null, typename T86 = Bits::Null,
+ Char const* k87 = Bits::null, typename T87 = Bits::Null,
+ Char const* k88 = Bits::null, typename T88 = Bits::Null,
+ Char const* k89 = Bits::null, typename T89 = Bits::Null,
+ Char const* k90 = Bits::null, typename T90 = Bits::Null,
+ Char const* k91 = Bits::null, typename T91 = Bits::Null,
+ Char const* k92 = Bits::null, typename T92 = Bits::Null,
+ Char const* k93 = Bits::null, typename T93 = Bits::Null,
+ Char const* k94 = Bits::null, typename T94 = Bits::Null,
+ Char const* k95 = Bits::null, typename T95 = Bits::Null,
+ Char const* k96 = Bits::null, typename T96 = Bits::Null,
+ Char const* k97 = Bits::null, typename T97 = Bits::Null,
+ Char const* k98 = Bits::null, typename T98 = Bits::Null,
+ Char const* k99 = Bits::null, typename T99 = Bits::Null,
+ Char const* k100 = Bits::null, typename T100 = Bits::Null>
+ class Options
+ {
+ typedef Bits::Mapper<k01, T01,
+ k02, T02,
+ k03, T03,
+ k04, T04,
+ k05, T05,
+ k06, T06,
+ k07, T07,
+ k08, T08,
+ k09, T09,
+ k10, T10,
+ k11, T11,
+ k12, T12,
+ k13, T13,
+ k14, T14,
+ k15, T15,
+ k16, T16,
+ k17, T17,
+ k18, T18,
+ k19, T19,
+ k20, T20,
+ k21, T21,
+ k22, T22,
+ k23, T23,
+ k24, T24,
+ k25, T25,
+ k26, T26,
+ k27, T27,
+ k28, T28,
+ k29, T29,
+ k30, T30,
+ k31, T31,
+ k32, T32,
+ k33, T33,
+ k34, T34,
+ k35, T35,
+ k36, T36,
+ k37, T37,
+ k38, T38,
+ k39, T39,
+ k40, T40,
+ k41, T41,
+ k42, T42,
+ k43, T43,
+ k44, T44,
+ k45, T45,
+ k46, T46,
+ k47, T47,
+ k48, T48,
+ k49, T49,
+ k50, T50,
+ k51, T51,
+ k52, T52,
+ k53, T53,
+ k54, T54,
+ k55, T55,
+ k56, T56,
+ k57, T57,
+ k58, T58,
+ k59, T59,
+ k60, T60,
+ k61, T61,
+ k62, T62,
+ k63, T63,
+ k64, T64,
+ k65, T65,
+ k66, T66,
+ k67, T67,
+ k68, T68,
+ k69, T69,
+ k70, T70,
+ k71, T71,
+ k72, T72,
+ k73, T73,
+ k74, T74,
+ k75, T75,
+ k76, T76,
+ k77, T77,
+ k78, T78,
+ k79, T79,
+ k80, T80,
+ k81, T81,
+ k82, T82,
+ k83, T83,
+ k84, T84,
+ k85, T85,
+ k86, T86,
+ k87, T87,
+ k88, T88,
+ k89, T89,
+ k90, T90,
+ k91, T91,
+ k92, T92,
+ k93, T93,
+ k94, T94,
+ k95, T95,
+ k96, T96,
+ k97, T97,
+ k98, T98,
+ k99, T99,
+ k100, T100> Mapper;
+
+ public:
+ Options ()
+ : i01_ (),
+ i02_ (),
+ i03_ (),
+ i04_ (),
+ i05_ (),
+ i06_ (),
+ i07_ (),
+ i08_ (),
+ i09_ (),
+ i10_ (),
+ i11_ (),
+ i12_ (),
+ i13_ (),
+ i14_ (),
+ i15_ (),
+ i16_ (),
+ i17_ (),
+ i18_ (),
+ i19_ (),
+ i20_ (),
+ i21_ (),
+ i22_ (),
+ i23_ (),
+ i24_ (),
+ i25_ (),
+ i26_ (),
+ i27_ (),
+ i28_ (),
+ i29_ (),
+ i30_ (),
+ i31_ (),
+ i32_ (),
+ i33_ (),
+ i34_ (),
+ i35_ (),
+ i36_ (),
+ i37_ (),
+ i38_ (),
+ i39_ (),
+ i40_ (),
+ i41_ (),
+ i42_ (),
+ i43_ (),
+ i44_ (),
+ i45_ (),
+ i46_ (),
+ i47_ (),
+ i48_ (),
+ i49_ (),
+ i50_ (),
+ i51_ (),
+ i52_ (),
+ i53_ (),
+ i54_ (),
+ i55_ (),
+ i56_ (),
+ i57_ (),
+ i58_ (),
+ i59_ (),
+ i60_ (),
+ i61_ (),
+ i62_ (),
+ i63_ (),
+ i64_ (),
+ i65_ (),
+ i66_ (),
+ i67_ (),
+ i68_ (),
+ i69_ (),
+ i70_ (),
+ i71_ (),
+ i72_ (),
+ i73_ (),
+ i74_ (),
+ i75_ (),
+ i76_ (),
+ i77_ (),
+ i78_ (),
+ i79_ (),
+ i80_ (),
+ i81_ (),
+ i82_ (),
+ i83_ (),
+ i84_ (),
+ i85_ (),
+ i86_ (),
+ i87_ (),
+ i88_ (),
+ i89_ (),
+ i90_ (),
+ i91_ (),
+ i92_ (),
+ i93_ (),
+ i94_ (),
+ i95_ (),
+ i96_ (),
+ i97_ (),
+ i98_ (),
+ i99_ (),
+ i100_ ()
+ {
+ }
+
+ template <Char const* k>
+ typename Mapper::template Selector<k>::Type&
+ value ()
+ {
+ typedef
+ typename Mapper::template Selector<k>::Type
+ Type;
+
+ return *reinterpret_cast<Type*> (value (k));
+ }
+
+ template <Char const* k>
+ typename Mapper::template Selector<k>::Type const&
+ value () const
+ {
+ typedef
+ typename Mapper::template Selector<k>::Type
+ Type;
+
+ return *reinterpret_cast<Type const*> (value (k));
+ }
+
+ private:
+ Void*
+ value (Char const*) const;
+
+ private:
+ T01 i01_;
+ T02 i02_;
+ T03 i03_;
+ T04 i04_;
+ T05 i05_;
+ T06 i06_;
+ T07 i07_;
+ T08 i08_;
+ T09 i09_;
+ T10 i10_;
+ T11 i11_;
+ T12 i12_;
+ T13 i13_;
+ T14 i14_;
+ T15 i15_;
+ T16 i16_;
+ T17 i17_;
+ T18 i18_;
+ T19 i19_;
+ T20 i20_;
+ T21 i21_;
+ T22 i22_;
+ T23 i23_;
+ T24 i24_;
+ T25 i25_;
+ T26 i26_;
+ T27 i27_;
+ T28 i28_;
+ T29 i29_;
+ T30 i30_;
+ T31 i31_;
+ T32 i32_;
+ T33 i33_;
+ T34 i34_;
+ T35 i35_;
+ T36 i36_;
+ T37 i37_;
+ T38 i38_;
+ T39 i39_;
+ T40 i40_;
+ T41 i41_;
+ T42 i42_;
+ T43 i43_;
+ T44 i44_;
+ T45 i45_;
+ T46 i46_;
+ T47 i47_;
+ T48 i48_;
+ T49 i49_;
+ T50 i50_;
+ T51 i51_;
+ T52 i52_;
+ T53 i53_;
+ T54 i54_;
+ T55 i55_;
+ T56 i56_;
+ T57 i57_;
+ T58 i58_;
+ T59 i59_;
+ T60 i60_;
+ T61 i61_;
+ T62 i62_;
+ T63 i63_;
+ T64 i64_;
+ T65 i65_;
+ T66 i66_;
+ T67 i67_;
+ T68 i68_;
+ T69 i69_;
+ T70 i70_;
+ T71 i71_;
+ T72 i72_;
+ T73 i73_;
+ T74 i74_;
+ T75 i75_;
+ T76 i76_;
+ T77 i77_;
+ T78 i78_;
+ T79 i79_;
+ T80 i80_;
+ T81 i81_;
+ T82 i82_;
+ T83 i83_;
+ T84 i84_;
+ T85 i85_;
+ T86 i86_;
+ T87 i87_;
+ T88 i88_;
+ T89 i89_;
+ T90 i90_;
+ T91 i91_;
+ T92 i92_;
+ T93 i93_;
+ T94 i94_;
+ T95 i95_;
+ T96 i96_;
+ T97 i97_;
+ T98 i98_;
+ T99 i99_;
+ T100 i100_;
+ };
+ }
+}
+
+#include <cult/cli/options.ixx>
+#include <cult/cli/options.txx>
+
+#endif // CULT_CLI_OPTIONS_HXX
diff --git a/libcult/cult/cli/options.ixx b/libcult/cult/cli/options.ixx
new file mode 100644
index 0000000..c25b833
--- /dev/null
+++ b/libcult/cult/cli/options.ixx
@@ -0,0 +1,12 @@
+// file : cult/cli/options.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace CLI
+ {
+ }
+}
+
diff --git a/libcult/cult/cli/options.txx b/libcult/cult/cli/options.txx
new file mode 100644
index 0000000..b26666d
--- /dev/null
+++ b/libcult/cult/cli/options.txx
@@ -0,0 +1,320 @@
+// file : cult/cli/options.txx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace CLI
+ {
+ template <Char const* k01, typename T01,
+ Char const* k02, typename T02,
+ Char const* k03, typename T03,
+ Char const* k04, typename T04,
+ Char const* k05, typename T05,
+ Char const* k06, typename T06,
+ Char const* k07, typename T07,
+ Char const* k08, typename T08,
+ Char const* k09, typename T09,
+ Char const* k10, typename T10,
+ Char const* k11, typename T11,
+ Char const* k12, typename T12,
+ Char const* k13, typename T13,
+ Char const* k14, typename T14,
+ Char const* k15, typename T15,
+ Char const* k16, typename T16,
+ Char const* k17, typename T17,
+ Char const* k18, typename T18,
+ Char const* k19, typename T19,
+ Char const* k20, typename T20,
+ Char const* k21, typename T21,
+ Char const* k22, typename T22,
+ Char const* k23, typename T23,
+ Char const* k24, typename T24,
+ Char const* k25, typename T25,
+ Char const* k26, typename T26,
+ Char const* k27, typename T27,
+ Char const* k28, typename T28,
+ Char const* k29, typename T29,
+ Char const* k30, typename T30,
+ Char const* k31, typename T31,
+ Char const* k32, typename T32,
+ Char const* k33, typename T33,
+ Char const* k34, typename T34,
+ Char const* k35, typename T35,
+ Char const* k36, typename T36,
+ Char const* k37, typename T37,
+ Char const* k38, typename T38,
+ Char const* k39, typename T39,
+ Char const* k40, typename T40,
+ Char const* k41, typename T41,
+ Char const* k42, typename T42,
+ Char const* k43, typename T43,
+ Char const* k44, typename T44,
+ Char const* k45, typename T45,
+ Char const* k46, typename T46,
+ Char const* k47, typename T47,
+ Char const* k48, typename T48,
+ Char const* k49, typename T49,
+ Char const* k50, typename T50,
+ Char const* k51, typename T51,
+ Char const* k52, typename T52,
+ Char const* k53, typename T53,
+ Char const* k54, typename T54,
+ Char const* k55, typename T55,
+ Char const* k56, typename T56,
+ Char const* k57, typename T57,
+ Char const* k58, typename T58,
+ Char const* k59, typename T59,
+ Char const* k60, typename T60,
+ Char const* k61, typename T61,
+ Char const* k62, typename T62,
+ Char const* k63, typename T63,
+ Char const* k64, typename T64,
+ Char const* k65, typename T65,
+ Char const* k66, typename T66,
+ Char const* k67, typename T67,
+ Char const* k68, typename T68,
+ Char const* k69, typename T69,
+ Char const* k70, typename T70,
+ Char const* k71, typename T71,
+ Char const* k72, typename T72,
+ Char const* k73, typename T73,
+ Char const* k74, typename T74,
+ Char const* k75, typename T75,
+ Char const* k76, typename T76,
+ Char const* k77, typename T77,
+ Char const* k78, typename T78,
+ Char const* k79, typename T79,
+ Char const* k80, typename T80,
+ Char const* k81, typename T81,
+ Char const* k82, typename T82,
+ Char const* k83, typename T83,
+ Char const* k84, typename T84,
+ Char const* k85, typename T85,
+ Char const* k86, typename T86,
+ Char const* k87, typename T87,
+ Char const* k88, typename T88,
+ Char const* k89, typename T89,
+ Char const* k90, typename T90,
+ Char const* k91, typename T91,
+ Char const* k92, typename T92,
+ Char const* k93, typename T93,
+ Char const* k94, typename T94,
+ Char const* k95, typename T95,
+ Char const* k96, typename T96,
+ Char const* k97, typename T97,
+ Char const* k98, typename T98,
+ Char const* k99, typename T99,
+ Char const* k100, typename T100>
+ Void*
+ Options<k01, T01,
+ k02, T02,
+ k03, T03,
+ k04, T04,
+ k05, T05,
+ k06, T06,
+ k07, T07,
+ k08, T08,
+ k09, T09,
+ k10, T10,
+ k11, T11,
+ k12, T12,
+ k13, T13,
+ k14, T14,
+ k15, T15,
+ k16, T16,
+ k17, T17,
+ k18, T18,
+ k19, T19,
+ k20, T20,
+ k21, T21,
+ k22, T22,
+ k23, T23,
+ k24, T24,
+ k25, T25,
+ k26, T26,
+ k27, T27,
+ k28, T28,
+ k29, T29,
+ k30, T30,
+ k31, T31,
+ k32, T32,
+ k33, T33,
+ k34, T34,
+ k35, T35,
+ k36, T36,
+ k37, T37,
+ k38, T38,
+ k39, T39,
+ k40, T40,
+ k41, T41,
+ k42, T42,
+ k43, T43,
+ k44, T44,
+ k45, T45,
+ k46, T46,
+ k47, T47,
+ k48, T48,
+ k49, T49,
+ k50, T50,
+ k51, T51,
+ k52, T52,
+ k53, T53,
+ k54, T54,
+ k55, T55,
+ k56, T56,
+ k57, T57,
+ k58, T58,
+ k59, T59,
+ k60, T60,
+ k61, T61,
+ k62, T62,
+ k63, T63,
+ k64, T64,
+ k65, T65,
+ k66, T66,
+ k67, T67,
+ k68, T68,
+ k69, T69,
+ k70, T70,
+ k71, T71,
+ k72, T72,
+ k73, T73,
+ k74, T74,
+ k75, T75,
+ k76, T76,
+ k77, T77,
+ k78, T78,
+ k79, T79,
+ k80, T80,
+ k81, T81,
+ k82, T82,
+ k83, T83,
+ k84, T84,
+ k85, T85,
+ k86, T86,
+ k87, T87,
+ k88, T88,
+ k89, T89,
+ k90, T90,
+ k91, T91,
+ k92, T92,
+ k93, T93,
+ k94, T94,
+ k95, T95,
+ k96, T96,
+ k97, T97,
+ k98, T98,
+ k99, T99,
+ k100, T100>::
+ value (Char const* k) const
+ {
+ Void* r (0);
+
+ if (k == k01) r = (Void*) (&i01_); else
+ if (k == k02) r = (Void*) (&i02_); else
+ if (k == k03) r = (Void*) (&i03_); else
+ if (k == k04) r = (Void*) (&i04_); else
+ if (k == k05) r = (Void*) (&i05_); else
+ if (k == k06) r = (Void*) (&i06_); else
+ if (k == k07) r = (Void*) (&i07_); else
+ if (k == k08) r = (Void*) (&i08_); else
+ if (k == k09) r = (Void*) (&i09_); else
+ if (k == k10) r = (Void*) (&i10_); else
+ if (k == k11) r = (Void*) (&i11_); else
+ if (k == k12) r = (Void*) (&i12_); else
+ if (k == k13) r = (Void*) (&i13_); else
+ if (k == k14) r = (Void*) (&i14_); else
+ if (k == k15) r = (Void*) (&i15_); else
+ if (k == k16) r = (Void*) (&i16_); else
+ if (k == k17) r = (Void*) (&i17_); else
+ if (k == k18) r = (Void*) (&i18_); else
+ if (k == k19) r = (Void*) (&i19_); else
+ if (k == k20) r = (Void*) (&i20_); else
+ if (k == k21) r = (Void*) (&i21_); else
+ if (k == k22) r = (Void*) (&i22_); else
+ if (k == k23) r = (Void*) (&i23_); else
+ if (k == k24) r = (Void*) (&i24_); else
+ if (k == k25) r = (Void*) (&i25_); else
+ if (k == k26) r = (Void*) (&i26_); else
+ if (k == k27) r = (Void*) (&i27_); else
+ if (k == k28) r = (Void*) (&i28_); else
+ if (k == k29) r = (Void*) (&i29_); else
+ if (k == k30) r = (Void*) (&i30_); else
+ if (k == k31) r = (Void*) (&i31_); else
+ if (k == k32) r = (Void*) (&i32_); else
+ if (k == k33) r = (Void*) (&i33_); else
+ if (k == k34) r = (Void*) (&i34_); else
+ if (k == k35) r = (Void*) (&i35_); else
+ if (k == k36) r = (Void*) (&i36_); else
+ if (k == k37) r = (Void*) (&i37_); else
+ if (k == k38) r = (Void*) (&i38_); else
+ if (k == k39) r = (Void*) (&i39_); else
+ if (k == k40) r = (Void*) (&i40_); else
+ if (k == k41) r = (Void*) (&i41_); else
+ if (k == k42) r = (Void*) (&i42_); else
+ if (k == k43) r = (Void*) (&i43_); else
+ if (k == k44) r = (Void*) (&i44_); else
+ if (k == k45) r = (Void*) (&i45_); else
+ if (k == k46) r = (Void*) (&i46_); else
+ if (k == k47) r = (Void*) (&i47_); else
+ if (k == k48) r = (Void*) (&i48_); else
+ if (k == k49) r = (Void*) (&i49_); else
+ if (k == k50) r = (Void*) (&i50_); else
+ if (k == k51) r = (Void*) (&i51_); else
+ if (k == k52) r = (Void*) (&i52_); else
+ if (k == k53) r = (Void*) (&i53_); else
+ if (k == k54) r = (Void*) (&i54_); else
+ if (k == k55) r = (Void*) (&i55_); else
+ if (k == k56) r = (Void*) (&i56_); else
+ if (k == k57) r = (Void*) (&i57_); else
+ if (k == k58) r = (Void*) (&i58_); else
+ if (k == k59) r = (Void*) (&i59_); else
+ if (k == k60) r = (Void*) (&i60_); else
+ if (k == k61) r = (Void*) (&i61_); else
+ if (k == k62) r = (Void*) (&i62_); else
+ if (k == k63) r = (Void*) (&i63_); else
+ if (k == k64) r = (Void*) (&i64_); else
+ if (k == k65) r = (Void*) (&i65_); else
+ if (k == k66) r = (Void*) (&i66_); else
+ if (k == k67) r = (Void*) (&i67_); else
+ if (k == k68) r = (Void*) (&i68_); else
+ if (k == k69) r = (Void*) (&i69_); else
+ if (k == k70) r = (Void*) (&i70_); else
+ if (k == k71) r = (Void*) (&i71_); else
+ if (k == k72) r = (Void*) (&i72_); else
+ if (k == k73) r = (Void*) (&i73_); else
+ if (k == k74) r = (Void*) (&i74_); else
+ if (k == k75) r = (Void*) (&i75_); else
+ if (k == k76) r = (Void*) (&i76_); else
+ if (k == k77) r = (Void*) (&i77_); else
+ if (k == k78) r = (Void*) (&i78_); else
+ if (k == k79) r = (Void*) (&i79_); else
+ if (k == k80) r = (Void*) (&i80_); else
+ if (k == k81) r = (Void*) (&i81_); else
+ if (k == k82) r = (Void*) (&i82_); else
+ if (k == k83) r = (Void*) (&i83_); else
+ if (k == k84) r = (Void*) (&i84_); else
+ if (k == k85) r = (Void*) (&i85_); else
+ if (k == k86) r = (Void*) (&i86_); else
+ if (k == k87) r = (Void*) (&i87_); else
+ if (k == k88) r = (Void*) (&i88_); else
+ if (k == k89) r = (Void*) (&i89_); else
+ if (k == k90) r = (Void*) (&i90_); else
+ if (k == k91) r = (Void*) (&i91_); else
+ if (k == k92) r = (Void*) (&i92_); else
+ if (k == k93) r = (Void*) (&i93_); else
+ if (k == k94) r = (Void*) (&i94_); else
+ if (k == k95) r = (Void*) (&i95_); else
+ if (k == k96) r = (Void*) (&i96_); else
+ if (k == k97) r = (Void*) (&i97_); else
+ if (k == k98) r = (Void*) (&i98_); else
+ if (k == k99) r = (Void*) (&i99_); else
+ if (k == k100) r = (Void*) (&i100_); else
+ assert (false);
+
+ return r;
+ }
+ }
+}
diff --git a/libcult/cult/cli/scanner.cxx b/libcult/cult/cli/scanner.cxx
new file mode 100644
index 0000000..af51bfa
--- /dev/null
+++ b/libcult/cult/cli/scanner.cxx
@@ -0,0 +1,17 @@
+// file : cult/cli/scanner.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/cli/scanner.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ Scanner::Action const Scanner::Action::keep (Scanner::Action::keep_);
+ Scanner::Action const Scanner::Action::erase (Scanner::Action::erase_);
+
+ Char const* const Scanner::eos = 0;
+ }
+}
diff --git a/libcult/cult/cli/scanner.hxx b/libcult/cult/cli/scanner.hxx
new file mode 100644
index 0000000..13fa804
--- /dev/null
+++ b/libcult/cult/cli/scanner.hxx
@@ -0,0 +1,132 @@
+// file : cult/cli/scanner.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CLI_SCANNER_HXX
+#define CULT_CLI_SCANNER_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/cli/exceptions.hxx>
+#include <cult/cli/arguments.hxx>
+
+namespace Cult
+{
+ namespace CLI
+ {
+ class Scanner: public NonCopyable
+ {
+ public:
+ class Action
+ {
+ public:
+ static Action const keep, erase;
+
+ friend Boolean
+ operator== (Action const& a, Action const& b)
+ {
+ return a.v_ == b.v_;
+ }
+
+ friend Boolean
+ operator!= (Action const& a, Action const& b)
+ {
+ return a.v_ != b.v_;
+ }
+
+ private:
+ enum Value { keep_, erase_ } v_;
+
+ Action (Value v)
+ : v_ (v)
+ {
+ }
+ };
+
+ public:
+ Scanner (Arguments& args, Action a = Action::keep, Index start = 1)
+ : cargs_ (args),
+ args_ (a == Action::erase ? &args : 0),
+ next_ (start)
+ {
+ }
+
+ Scanner (Arguments const& args, Index start = 1)
+ : cargs_ (args), args_ (0), next_ (start)
+ {
+ }
+
+ public:
+ static Char const* const eos;
+
+ class PastEOS: public virtual Exception {};
+
+ Char const*
+ next ()
+ {
+ if (next_ > cargs_.size ())
+ {
+ throw PastEOS ();
+ }
+ else if (next_ == cargs_.size ())
+ {
+ ++next_;
+ return eos;
+ }
+ else
+ {
+ Char const* r (cargs_[next_]);
+
+ if (args_ != 0)
+ {
+ hold_ = r;
+ args_->erase (next_);
+ return hold_.c_str ();
+ }
+ else
+ {
+ ++next_;
+ return r;
+ }
+ }
+ }
+
+ Char const*
+ peek ()
+ {
+ if (next_ > cargs_.size ())
+ {
+ throw PastEOS ();
+ }
+ else if (next_ == cargs_.size ())
+ {
+ return eos;
+ }
+ else
+ {
+ return cargs_[next_];
+ }
+ }
+
+ Void
+ skip ()
+ {
+ if (next_ > cargs_.size ())
+ throw PastEOS ();
+ else
+ ++next_;
+ }
+
+ private:
+ Arguments const& cargs_;
+ Arguments* args_;
+ Index next_;
+ String hold_;
+ };
+ }
+}
+
+#include <cult/cli/scanner.ixx>
+
+#endif // CULT_CLI_SCANNER_HXX
diff --git a/libcult/cult/cli/scanner.ixx b/libcult/cult/cli/scanner.ixx
new file mode 100644
index 0000000..5e84451
--- /dev/null
+++ b/libcult/cult/cli/scanner.ixx
@@ -0,0 +1,12 @@
+// file : cult/cli/scanner.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace CLI
+ {
+ }
+}
+
diff --git a/libcult/cult/containers/any.hxx b/libcult/cult/containers/any.hxx
new file mode 100644
index 0000000..10f771f
--- /dev/null
+++ b/libcult/cult/containers/any.hxx
@@ -0,0 +1,192 @@
+// file : cult/containers/any.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CONTAINERS_ANY_HXX
+#define CULT_CONTAINERS_ANY_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/rtti/type-id.hxx>
+
+namespace Cult
+{
+ namespace Containers
+ {
+ //@@ eager clonning: do I need it?
+ //
+ //
+ class Any
+ {
+ public:
+ struct Typing {};
+
+ public:
+ template <typename X>
+ Any (X const& x)
+ : holder_ (new HolderTemplate<X> (x))
+ {
+ }
+
+ Any (Any const& any)
+ : holder_ (any.holder_->clone ())
+ {
+ }
+
+ public:
+ template <typename X>
+ Any&
+ operator= (X const& x)
+ {
+ holder_ = Evptr<Holder> (new HolderTemplate<X> (x));
+ return *this;
+ }
+
+ Any&
+ operator= (Any const& any)
+ {
+ holder_ = any.holder_->clone ();
+ return *this;
+ }
+
+ public:
+ /*
+ template <typename X>
+ operator X& ()
+ {
+ return value<X> ();
+ }
+
+ template <typename X>
+ operator X const& () const
+ {
+ return value<X> ();
+ }
+ */
+
+ public:
+ template <typename X>
+ X&
+ value ()
+ {
+ //@@ too strict
+ //
+ if (holder_->type_id () == typeid (X))
+ {
+ return dynamic_cast<HolderTemplate<X>*>(holder_.get ())->value ();
+ }
+ else
+ {
+ throw Typing ();
+ }
+ }
+
+ template <typename X>
+ X const&
+ value () const
+ {
+ if (holder_->type_id () == typeid (X))
+ {
+ return dynamic_cast<HolderTemplate<X>*>(holder_.get ())->value ();
+ }
+ else
+ {
+ throw Typing ();
+ }
+ }
+
+ public:
+ RTTI::TypeId
+ type_id () const
+ {
+ return holder_->type_id ();
+ }
+
+ public:
+ /*
+ template <typename x>
+ friend x
+ operator+ (any const& a, x const& b)
+ {
+ return a.value<x> () + b;
+ }
+
+ template <typename x>
+ friend x
+ operator+ (x const& a, any const& b)
+ {
+ return a + b.value<x> ();
+ }
+ */
+
+ private:
+ class Holder
+ {
+ public:
+ virtual
+ ~Holder ()
+ {
+ }
+
+ Evptr<Holder>
+ clone () const
+ {
+ return clone_ ();
+ }
+
+ virtual RTTI::TypeId
+ type_id () const = 0;
+
+ protected:
+ virtual Evptr<Holder>
+ clone_ () const = 0;
+ };
+
+ template <typename X>
+ class HolderTemplate : public Holder
+ {
+ public:
+ HolderTemplate (X const& value)
+ : value_ (value)
+ {
+ }
+
+ virtual RTTI::TypeId
+ type_id () const
+ {
+ return RTTI::TypeId (typeid (value_));
+ }
+
+ X const&
+ value () const
+ {
+ return value_;
+ }
+
+ X&
+ value ()
+ {
+ return value_;
+ }
+
+ protected:
+ virtual Evptr<Holder>
+ clone_ () const
+ {
+ return new HolderTemplate<X> (value_);
+ }
+
+ private:
+ X value_;
+ };
+
+ private:
+ Evptr<Holder> holder_;
+ };
+ }
+}
+
+#include <cult/containers/any.txx>
+
+#endif // CULT_CONTAINERS_ANY_HXX
diff --git a/libcult/cult/containers/any.txx b/libcult/cult/containers/any.txx
new file mode 100644
index 0000000..8e97345
--- /dev/null
+++ b/libcult/cult/containers/any.txx
@@ -0,0 +1,11 @@
+// file : cult/containers/any.txx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Containers
+ {
+ }
+}
diff --git a/libcult/cult/containers/deque.hxx b/libcult/cult/containers/deque.hxx
new file mode 100644
index 0000000..ed17a0c
--- /dev/null
+++ b/libcult/cult/containers/deque.hxx
@@ -0,0 +1,166 @@
+// file : cult/containers/deque.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CONTAINERS_DEQUE_HXX
+#define CULT_CONTAINERS_DEQUE_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/iterator.hxx>
+
+#include <deque>
+
+namespace Cult
+{
+ namespace Containers
+ {
+ template <typename T>
+ class Deque: public std::deque<T>
+ {
+ typedef std::deque<T> Base;
+
+ Base&
+ base ()
+ {
+ return *this;
+ }
+
+ Base const&
+ base () const
+ {
+ return *this;
+ }
+
+ public:
+ typedef typename Base::value_type Value;
+
+
+ typedef typename Base::reference Reference;
+ typedef typename Base::const_reference ConstReference;
+
+
+ typedef typename Base::pointer Pointer;
+ typedef typename Base::const_pointer ConstPointer;
+
+
+ typedef
+ IteratorAdapter<typename Base::iterator>
+ Iterator;
+
+ typedef
+ IteratorAdapter<typename Base::const_iterator>
+ ConstIterator;
+
+
+ typedef
+ IteratorAdapter<typename Base::reverse_iterator>
+ ReverseIterator;
+
+ typedef
+ IteratorAdapter<typename Base::const_reverse_iterator>
+ ConstReverseIterator;
+
+
+ // Use Cult::Size and Cult::PtrDifference.
+ //
+ // typedef Base::size_type;
+ // typedef Base::difference_type;
+
+ public:
+ explicit
+ Deque ()
+ : Base ()
+ {
+ }
+
+ explicit
+ Deque (Size size, Value const& value = Value ())
+ : Base (size, value)
+ {
+ }
+
+ template <typename InputIterator>
+ Deque (InputIterator first, InputIterator last)
+ : Base (first, last)
+ {
+ }
+
+ Deque (Deque<Value> const& other)
+ : Base (other)
+ {
+ }
+
+ Deque<Value>&
+ operator= (Deque<Value> const& other)
+ {
+ base () = other;
+ return *this;
+ }
+
+ public:
+ Iterator
+ begin ()
+ {
+ return Iterator (base ().begin ());
+ }
+
+ Iterator
+ end ()
+ {
+ return Iterator (base ().end ());
+ }
+
+
+ ConstIterator
+ begin () const
+ {
+ return ConstIterator (base ().begin ());
+ }
+
+ ConstIterator
+ end () const
+ {
+ return ConstIterator (base ().end ());
+ }
+
+ //
+ //
+
+ ReverseIterator
+ rbegin ()
+ {
+ return ReverseIterator (base ().rbegin ());
+ }
+
+ ReverseIterator
+ rend ()
+ {
+ return ReverseIterator (base ().rend ());
+ }
+
+
+ ConstReverseIterator
+ rbegin () const
+ {
+ return ConstReverseIterator (base ().rbegin ());
+ }
+
+ ConstReverseIterator
+ rend () const
+ {
+ return ConstReverseIterator (base ().rend ());
+ }
+
+ public:
+ Void
+ swap (Deque<Value>& other)
+ {
+ base ().swap (other);
+ }
+ };
+ }
+}
+
+#endif // CULT_CONTAINERS_DEQUE_HXX
diff --git a/libcult/cult/containers/graph.hxx b/libcult/cult/containers/graph.hxx
new file mode 100644
index 0000000..d61cd53
--- /dev/null
+++ b/libcult/cult/containers/graph.hxx
@@ -0,0 +1,193 @@
+// file : cult/containers/graph.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CONTAINERS_GRAPH_HXX
+#define CULT_CONTAINERS_GRAPH_HXX
+
+#include <cult/types.hxx>
+#include <cult/eh/exception.hxx>
+#include <cult/containers/map.hxx>
+
+namespace Cult
+{
+ namespace Containers
+ {
+ template <typename N, typename E>
+ class Graph
+ {
+ public:
+ typedef N Node;
+ typedef E Edge;
+
+ struct NoEdge: virtual EH::Exception {};
+ struct NoNode: virtual EH::Exception {};
+
+ public:
+ template <typename T>
+ T&
+ new_node ();
+
+ template <typename T, typename A0>
+ T&
+ new_node (A0 const&);
+
+ template <typename T, typename A0, typename A1>
+ T&
+ new_node (A0 const&, A1 const&);
+
+ template <typename T, typename A0, typename A1, typename A2>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&, A7 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&, A7 const&, A8 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8, typename A9>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&, A7 const&, A8 const&, A9 const&);
+
+ public:
+ template <typename T, typename Left, typename Right>
+ T&
+ new_edge (Left&, Right&);
+
+ template <typename T, typename Left, typename Right,
+ typename A0>
+ T&
+ new_edge (Left&, Right&, A0 const&);
+
+ template <typename T, typename Left, typename Right,
+ typename A0, typename A1>
+ T&
+ new_edge (Left&, Right&, A0 const&, A1 const&);
+
+ template <typename T, typename Left, typename Right,
+ typename A0, typename A1, typename A2>
+ T&
+ new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&);
+
+ template <typename T, typename Left, typename Right,
+ typename A0, typename A1, typename A2, typename A3>
+ T&
+ new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&, A3 const&);
+
+ template <typename T, typename Left, typename Right,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4>
+ T&
+ new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&, A3 const&,
+ A4 const&);
+
+ template <typename T, typename Left, typename Right,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4, typename A5>
+ T&
+ new_edge (Left&, Right&, A0 const&, A1 const&, A2 const&, A3 const&,
+ A4 const&, A5 const&);
+
+ // Functions to reset edge's nodes.
+ //
+ public:
+ template <typename TE, typename TN>
+ Void
+ reset_left_node (TE& edge, TN& node)
+ {
+ edge.set_left_node (node);
+ }
+
+ template <typename TE, typename TN>
+ Void
+ reset_right_node (TE& edge, TN& node)
+ {
+ edge.set_right_node (node);
+ }
+
+ // Functions to add edges to a node.
+ //
+ public:
+ template <typename TN, typename TE>
+ Void
+ add_edge_left (TN& node, TE& edge)
+ {
+ node.add_edge_left (edge);
+ }
+
+ template <typename TN, typename TE>
+ Void
+ add_edge_right (TN& node, TE& edge)
+ {
+ node.add_edge_right (edge);
+ }
+
+ // Functions to delete edges and nodes. In order to delete a
+ // a node without leaving any dangling edges you need to make
+ // sure that each edge pointing to it is either deleted or reset
+ // to some other node.
+ //
+ public:
+ template <typename T, typename Left, typename Right>
+ Void
+ delete_edge (Left& left_node, Right& right_node, T& edge);
+
+ Void
+ delete_node (Node& node)
+ {
+ if (nodes_.erase (&node) == 0)
+ throw NoNode ();
+ }
+
+ protected:
+ typedef Shptr<Node> NodePtr;
+ typedef Shptr<Edge> EdgePtr;
+
+ typedef Map<Node*, NodePtr> Nodes;
+ typedef Map<Edge*, EdgePtr> Edges;
+
+ Nodes nodes_;
+ Edges edges_;
+ };
+ }
+}
+
+
+#include <cult/containers/graph.txx>
+
+#endif // CULT_CONTAINERS_GRAPH_HXX
diff --git a/libcult/cult/containers/graph.txx b/libcult/cult/containers/graph.txx
new file mode 100644
index 0000000..a9c9979
--- /dev/null
+++ b/libcult/cult/containers/graph.txx
@@ -0,0 +1,313 @@
+// file : cult/containers/graph.txx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Containers
+ {
+
+ // Nodes.
+ //
+
+ template <typename N, typename E>
+ template <typename T>
+ T& Graph<N, E>::
+ new_node ()
+ {
+ Shptr<T> node (new T);
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0>
+ T& Graph<N, E>::
+ new_node (A0 const& a0)
+ {
+ Shptr<T> node (new T (a0));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1>
+ T& Graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1)
+ {
+ Shptr<T> node (new T (a0, a1));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2>
+ T& Graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2)
+ {
+ Shptr<T> node (new T (a0, a1, a2));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3>
+ T& Graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3)
+ {
+ Shptr<T> node (new T (a0, a1, a2, a3));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4>
+ T& Graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4)
+ {
+ Shptr<T> node (new T (a0, a1, a2, a3, a4));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5>
+ T& Graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5)
+ {
+ Shptr<T> node (new T (a0, a1, a2, a3, a4, a5));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6>
+ T& Graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6)
+ {
+ Shptr<T> node (new T (a0, a1, a2, a3, a4, a5, a6));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7>
+ T& Graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7)
+ {
+ Shptr<T> node (new T (a0, a1, a2, a3, a4, a5, a6, a7));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8>
+ T& Graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7,
+ A8 const& a8)
+ {
+ Shptr<T> node (new T (a0, a1, a2, a3, a4, a5, a6, a7, a8));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8, typename A9>
+ T& Graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7,
+ A8 const& a8, A9 const& a9)
+ {
+ Shptr<T> node (new T (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ // Edges.
+ //
+
+ template <typename N, typename E>
+ template <typename T, typename Left, typename Right>
+ T& Graph<N, E>::
+ new_edge (Left& l, Right& r)
+ {
+ Shptr<T> edge (new T);
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename Left, typename Right,
+ typename A0>
+ T& Graph<N, E>::
+ new_edge (Left& l, Right& r, A0 const& a0)
+ {
+ Shptr<T> edge (new T (a0));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename Left, typename Right,
+ typename A0, typename A1>
+ T& Graph<N, E>::
+ new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1)
+ {
+ Shptr<T> edge (new T (a0, a1));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename Left, typename Right,
+ typename A0, typename A1, typename A2>
+ T& Graph<N, E>::
+ new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2)
+ {
+ Shptr<T> edge (new T (a0, a1, a2));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename Left, typename Right,
+ typename A0, typename A1, typename A2, typename A3>
+ T& Graph<N, E>::
+ new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2,
+ A3 const& a3)
+ {
+ Shptr<T> edge (new T (a0, a1, a2, a3));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename Left, typename Right,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4>
+ T& Graph<N, E>::
+ new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2,
+ A3 const& a3, A4 const& a4)
+ {
+ Shptr<T> edge (new T (a0, a1, a2, a3, a4));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename Left, typename Right,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4, typename A5>
+ T& Graph<N, E>::
+ new_edge (Left& l, Right& r, A0 const& a0, A1 const& a1, A2 const& a2,
+ A3 const& a3, A4 const& a4, A5 const& a5)
+ {
+ Shptr<T> edge (new T (a0, a1, a2, a3, a4, a5));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename Left, typename Right>
+ Void Graph<N, E>::
+ delete_edge (Left& l, Right& r, T& edge)
+ {
+ typename Edges::Iterator i (edges_.find (&edge));
+
+ if (i == edges_.end () ||
+ nodes_.find (&l) == nodes_.end () ||
+ nodes_.find (&r) == nodes_.end ())
+ throw NoEdge ();
+
+ r.remove_edge_right (edge);
+ l.remove_edge_left (edge);
+
+ edge.clear_right_node (r);
+ edge.clear_left_node (l);
+
+ edges_.erase (i);
+ }
+ }
+}
diff --git a/libcult/cult/containers/iterator.hxx b/libcult/cult/containers/iterator.hxx
new file mode 100644
index 0000000..132043b
--- /dev/null
+++ b/libcult/cult/containers/iterator.hxx
@@ -0,0 +1,227 @@
+// file : cult/containers/iterator.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CONTAINERS_ITERATOR_HXX
+#define CULT_CONTAINERS_ITERATOR_HXX
+
+#include <cult/types.hxx>
+
+#include <iterator>
+
+namespace Cult
+{
+ namespace Containers
+ {
+ template <typename I>
+ class IteratorAdapter
+ {
+ public:
+ typedef typename std::iterator_traits<I>::value_type Value;
+ typedef typename std::iterator_traits<I>::difference_type Difference;
+ typedef typename std::iterator_traits<I>::pointer Pointer;
+ typedef typename std::iterator_traits<I>::reference Reference;
+ typedef typename std::iterator_traits<I>::iterator_category Category;
+
+ // For compatibility with std::iterator_traits
+ //
+ public:
+ typedef Value value_type;
+ typedef Reference reference;
+ typedef Pointer pointer;
+ typedef Category iterator_category;
+ typedef Difference difference_type;
+
+ public:
+ IteratorAdapter ()
+ : i_ () // i_ can be of a pointer type.
+ {
+ }
+
+ explicit
+ IteratorAdapter (I const& i)
+ : i_ (i)
+ {
+ }
+
+ template <typename J>
+ IteratorAdapter (IteratorAdapter<J> const& j)
+ : i_ (j.i_)
+ {
+ }
+ public:
+ // Forward iterator requirements.
+ //
+ Reference
+ operator* () const
+ {
+ return *i_;
+ }
+
+ Pointer
+ operator-> () const
+ {
+ return &(*i_);
+ }
+
+ IteratorAdapter&
+ operator++ ()
+ {
+ ++i_;
+ return *this;
+ }
+
+ IteratorAdapter
+ operator++ (Int)
+ {
+ return IteratorAdapter (i_++);
+ }
+
+ public:
+ // Bidirectional iterator requirements.
+ //
+ IteratorAdapter&
+ operator-- ()
+ {
+ --i_;
+ return *this;
+ }
+
+ IteratorAdapter
+ operator-- (Int)
+ {
+ return IteratorAdapter (i_--);
+ }
+
+ public:
+ // Random access iterator requirements.
+ //
+ Reference
+ operator[] (Difference n) const
+ {
+ return i_[n];
+ }
+
+ IteratorAdapter
+ operator+ (Difference n) const
+ {
+ return IteratorAdapter (i_ + n);
+ }
+
+ IteratorAdapter&
+ operator+= (Difference n)
+ {
+ i_ += n;
+ return *this;
+ }
+
+ IteratorAdapter
+ operator- (Difference n) const
+ {
+ return IteratorAdapter (i_ - n);
+ }
+
+ IteratorAdapter&
+ operator-= (Difference n)
+ {
+ i_ += n;
+ return *this;
+ }
+
+ public:
+ I const&
+ base () const
+ {
+ return i_;
+ }
+
+ // @@ This is needed so that call to functions such as erase()
+ // be possible without writing a wrapper. This should be a temporary
+ // measure.
+
+ operator I& ()
+ {
+ return i_;
+ }
+
+ operator I const& () const
+ {
+ return i_;
+ }
+
+ private:
+ template<typename>
+ friend class IteratorAdapter;
+
+ I i_;
+ };
+
+ // Note: We use different types for left- and right-hand-side
+ // arguments to allow comparison between iterator and const_iterator.
+ //
+
+ // Forward iterator requirements.
+ //
+ template <typename I, typename J>
+ inline Boolean
+ operator== (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j)
+ {
+ return i.base () == j.base ();
+ }
+
+ template <typename I, typename J>
+ inline Boolean
+ operator!= (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j)
+ {
+ return i.base () != j.base ();
+ }
+
+ // Random access iterator requirements
+ //
+ template <typename I, typename J>
+ inline Boolean
+ operator< (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j)
+ {
+ return i.base() < j.base();
+ }
+
+ template <typename I, typename J>
+ inline Boolean
+ operator> (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j)
+ {
+ return i.base() > j.base();
+ }
+
+ template <typename I, typename J>
+ inline Boolean
+ operator<= (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j)
+ {
+ return i.base() <= j.base();
+ }
+
+ template <typename I, typename J>
+ inline Boolean
+ operator>= (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j)
+ {
+ return i.base() >= j.base();
+ }
+
+ template <typename I, typename J>
+ inline typename IteratorAdapter<I>::Difference
+ operator- (IteratorAdapter<I> const& i, IteratorAdapter<J> const& j)
+ {
+ return i.base () - j.base ();
+ }
+
+ template <typename I>
+ IteratorAdapter<I>
+ operator+ (typename IteratorAdapter<I>::Difference n,
+ IteratorAdapter<I> const& x)
+ {
+ return x + n;
+ }
+ }
+}
+
+#endif // CULT_CONTAINERS_ITERATOR_HXX
diff --git a/libcult/cult/containers/list.hxx b/libcult/cult/containers/list.hxx
new file mode 100644
index 0000000..161052e
--- /dev/null
+++ b/libcult/cult/containers/list.hxx
@@ -0,0 +1,193 @@
+// file : cult/containers/list.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CONTAINERS_LIST_HXX
+#define CULT_CONTAINERS_LIST_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/iterator.hxx>
+
+#include <list>
+
+namespace Cult
+{
+ namespace Containers
+ {
+ template <typename T>
+ class List: public std::list<T>
+ {
+ typedef std::list<T> Base;
+
+ Base&
+ base ()
+ {
+ return *this;
+ }
+
+ Base const&
+ base () const
+ {
+ return *this;
+ }
+
+ public:
+ typedef typename Base::value_type Value;
+
+ typedef typename Base::reference Reference;
+ typedef typename Base::const_reference ConstReference;
+
+ typedef typename Base::pointer Pointer;
+ typedef typename Base::const_pointer ConstPointer;
+
+
+ typedef
+ IteratorAdapter<typename Base::iterator>
+ Iterator;
+
+ typedef
+ IteratorAdapter<typename Base::const_iterator>
+ ConstIterator;
+
+
+ typedef
+ IteratorAdapter<typename Base::reverse_iterator>
+ ReverseIterator;
+
+ typedef
+ IteratorAdapter<typename Base::const_reverse_iterator>
+ ConstReverseIterator;
+
+
+ // Use Cult::Size and Cult::PtrDifference.
+ //
+ // typedef Base::size_type;
+ // typedef Base::difference_type;
+
+ public:
+ explicit
+ List ()
+ : Base ()
+ {
+ }
+
+ explicit
+ List (Size size, Value const& value = Value ())
+ : Base (size, value)
+ {
+ }
+
+ template <typename InputIterator>
+ List (InputIterator first, InputIterator last)
+ : Base (first, last)
+ {
+ }
+
+ List (List<Value> const& other)
+ : Base (other)
+ {
+ }
+
+ List<Value>&
+ operator= (List<Value> const& other)
+ {
+ base () = other;
+ return *this;
+ }
+
+ public:
+ Void
+ swap (List<Value>& other)
+ {
+ base ().swap (other);
+ }
+
+ public:
+ Iterator
+ begin ()
+ {
+ return Iterator (base ().begin ());
+ }
+
+ Iterator
+ end ()
+ {
+ return Iterator (base ().end ());
+ }
+
+
+ ConstIterator
+ begin () const
+ {
+ return ConstIterator (base ().begin ());
+ }
+
+ ConstIterator
+ end () const
+ {
+ return ConstIterator (base ().end ());
+ }
+
+ //
+ //
+
+ ReverseIterator
+ rbegin ()
+ {
+ return ReverseIterator (base ().rbegin ());
+ }
+
+ ReverseIterator
+ rend ()
+ {
+ return ReverseIterator (base ().rend ());
+ }
+
+
+ ConstReverseIterator
+ rbegin () const
+ {
+ return ConstReverseIterator (base ().rbegin ());
+ }
+
+ ConstReverseIterator
+ rend () const
+ {
+ return ConstReverseIterator (base ().rend ());
+ }
+
+ public:
+ Iterator
+ insert (Iterator const& p, Value const& x)
+ {
+ return Iterator (base ().insert (p.base (), x));
+ }
+
+ template <typename I>
+ Void
+ insert (Iterator const& p, I const& first, I const& last)
+ {
+ base ().insert (p.base (), first, last);
+ }
+
+ template <typename I>
+ Void
+ insert (Iterator const& p,
+ IteratorAdapter<I> const& first,
+ IteratorAdapter<I> const& last)
+ {
+ base ().insert (p.base (), first.base (), last.base ());
+ }
+
+ Iterator
+ erase (Iterator const& i)
+ {
+ return Iterator (base ().erase (i.base ()));
+ }
+ };
+ }
+}
+
+#endif // CULT_CONTAINERS_LIST_HXX
diff --git a/libcult/cult/containers/map.hxx b/libcult/cult/containers/map.hxx
new file mode 100644
index 0000000..8a3fbdb
--- /dev/null
+++ b/libcult/cult/containers/map.hxx
@@ -0,0 +1,175 @@
+// file : cult/containers/map.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CONTAINERS_MAP_HXX
+#define CULT_CONTAINERS_MAP_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/iterator.hxx>
+
+#include <map>
+
+namespace Cult
+{
+ namespace Containers
+ {
+ template <typename K, typename T, typename C = std::less<K> >
+ class Map: public std::map<K, T, C>
+ {
+ typedef std::map<K, T, C> Base;
+
+ Base&
+ base ()
+ {
+ return *this;
+ }
+
+ Base const&
+ base () const
+ {
+ return *this;
+ }
+
+ public:
+ typedef typename Base::key_type Key;
+ typedef typename Base::mapped_type Value;
+ typedef typename Base::value_type Pair;
+ typedef typename Base::key_compare Compare;
+
+ typedef typename Base::reference Reference;
+ typedef typename Base::const_reference ConstReference;
+
+ typedef typename Base::pointer Pointer;
+ typedef typename Base::const_pointer ConstPointer;
+
+
+ typedef
+ IteratorAdapter<typename Base::iterator>
+ Iterator;
+
+ typedef
+ IteratorAdapter<typename Base::const_iterator>
+ ConstIterator;
+
+
+ typedef
+ IteratorAdapter<typename Base::reverse_iterator>
+ ReverseIterator;
+
+ typedef
+ IteratorAdapter<typename Base::const_reverse_iterator>
+ ConstReverseIterator;
+
+ // Use Cult::Size and Cult::PtrDifference.
+ //
+ // typedef Base::size_type;
+ // typedef Base::difference_type;
+
+ public:
+ explicit
+ Map (Compare const& comp = Compare ())
+ : Base (comp)
+ {
+ }
+
+ template <typename InputIterator>
+ Map (InputIterator first,
+ InputIterator last,
+ Compare const& comp = Compare ())
+ : Base (first, last, comp)
+ {
+ }
+
+ Map (Map<Key, Value, Compare> const& other)
+ : Base (other)
+ {
+ }
+
+ Map<Key, Value, Compare>&
+ operator= (Map<Key, Value, Compare> const& other)
+ {
+ base () = other;
+ return *this;
+ }
+
+ public:
+ Iterator
+ begin ()
+ {
+ return Iterator (base ().begin ());
+ }
+
+ Iterator
+ end ()
+ {
+ return Iterator (base ().end ());
+ }
+
+
+ ConstIterator
+ begin () const
+ {
+ return ConstIterator (base ().begin ());
+ }
+
+ ConstIterator
+ end () const
+ {
+ return ConstIterator (base ().end ());
+ }
+
+ //
+ //
+
+ ReverseIterator
+ rbegin ()
+ {
+ return ReverseIterator (base ().rbegin ());
+ }
+
+ ReverseIterator
+ rend ()
+ {
+ return ReverseIterator (base ().rend ());
+ }
+
+
+ ConstReverseIterator
+ rbegin () const
+ {
+ return ConstReverseIterator (base ().rbegin ());
+ }
+
+ ConstReverseIterator
+ rend () const
+ {
+ return ConstReverseIterator (base ().rend ());
+ }
+
+ public:
+ Iterator
+ find (Key const& k)
+ {
+ return Iterator (base ().find (k));
+ }
+
+ ConstIterator
+ find (Key const& k) const
+ {
+ return ConstIterator (base ().find (k));
+ }
+
+ public:
+ Void
+ swap (Map<Key, Value, Compare>& other)
+ {
+ base ().swap (other);
+ }
+ };
+ }
+}
+
+#endif // CULT_CONTAINERS_MAP_HXX
diff --git a/libcult/cult/containers/pair.hxx b/libcult/cult/containers/pair.hxx
new file mode 100644
index 0000000..b8b7506
--- /dev/null
+++ b/libcult/cult/containers/pair.hxx
@@ -0,0 +1,58 @@
+// file : cult/containers/pair.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CONTAINERS_PAIR_HXX
+#define CULT_CONTAINERS_PAIR_HXX
+
+#include <utility>
+
+namespace Cult
+{
+ namespace Containers
+ {
+ template <typename T1, typename T2>
+ class Pair: public std::pair<T1, T2>
+ {
+ typedef std::pair<T1, T2> Base;
+
+ Base&
+ base ()
+ {
+ return *this;
+ }
+
+ public:
+ typedef T1 First;
+ typedef T2 Second;
+
+ public:
+ Pair ()
+ : Base ()
+ {
+ }
+
+ Pair (First const& first, Second const& second)
+ : Base (first, second)
+ {
+ }
+
+ template <typename X, typename Y>
+ Pair (std::pair<X, Y> const& pair)
+ : Base (pair)
+ {
+ }
+
+ template <typename X, typename Y>
+ Pair&
+ operator= (std::pair<X, Y> const& pair)
+ {
+ base () = pair;
+ return *this;
+ }
+ };
+ }
+}
+
+#endif // CULT_CONTAINERS_PAIR_HXX
diff --git a/libcult/cult/containers/set.hxx b/libcult/cult/containers/set.hxx
new file mode 100644
index 0000000..a911c19
--- /dev/null
+++ b/libcult/cult/containers/set.hxx
@@ -0,0 +1,175 @@
+// file : cult/containers/set.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CONTAINERS_SET_HXX
+#define CULT_CONTAINERS_SET_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/iterator.hxx>
+
+#include <set>
+
+namespace Cult
+{
+ namespace Containers
+ {
+ template <typename K, typename C = std::less<K> >
+ class Set: public std::set<K, C>
+ {
+ typedef std::set<K, C> Base;
+
+ Base&
+ base ()
+ {
+ return *this;
+ }
+
+ Base const&
+ base () const
+ {
+ return *this;
+ }
+
+ public:
+ typedef typename Base::key_type Key;
+ typedef typename Base::value_type Value; // Same as Key.
+ typedef typename Base::key_compare Compare;
+
+ typedef typename Base::reference Reference;
+ typedef typename Base::const_reference ConstReference;
+
+ typedef typename Base::pointer Pointer;
+ typedef typename Base::const_pointer ConstPointer;
+
+
+ typedef
+ IteratorAdapter<typename Base::iterator>
+ Iterator;
+
+ typedef
+ IteratorAdapter<typename Base::const_iterator>
+ ConstIterator;
+
+
+ typedef
+ IteratorAdapter<typename Base::reverse_iterator>
+ ReverseIterator;
+
+ typedef
+ IteratorAdapter<typename Base::const_reverse_iterator>
+ ConstReverseIterator;
+
+
+ // Use Cult::Size and Cult::PtrDifference.
+ //
+ // typedef Base::size_type;
+ // typedef Base::difference_type;
+
+ public:
+ explicit
+ Set (Compare const& comp = Compare ())
+ : Base (comp)
+ {
+ }
+
+ template <typename InputIterator>
+ Set (InputIterator first,
+ InputIterator last,
+ Compare const& comp = Compare ())
+ : Base (first, last, comp)
+ {
+ }
+
+ Set (Set<Key, Compare> const& other)
+ : Base (other)
+ {
+ }
+
+ Set<Key, Compare>&
+ operator= (Set<Key, Compare> const& other)
+ {
+ base () = other;
+ return *this;
+ }
+
+ public:
+ Iterator
+ begin ()
+ {
+ return Iterator (base ().begin ());
+ }
+
+ Iterator
+ end ()
+ {
+ return Iterator (base ().end ());
+ }
+
+
+ ConstIterator
+ begin () const
+ {
+ return ConstIterator (base ().begin ());
+ }
+
+ ConstIterator
+ end () const
+ {
+ return ConstIterator (base ().end ());
+ }
+
+ //
+ //
+
+ ReverseIterator
+ rbegin ()
+ {
+ return ReverseIterator (base ().rbegin ());
+ }
+
+ ReverseIterator
+ rend ()
+ {
+ return ReverseIterator (base ().rend ());
+ }
+
+
+ ConstReverseIterator
+ rbegin () const
+ {
+ return ConstReverseIterator (base ().rbegin ());
+ }
+
+ ConstReverseIterator
+ rend () const
+ {
+ return ConstReverseIterator (base ().rend ());
+ }
+
+ public:
+ Iterator
+ find (Key const& k)
+ {
+ return Iterator (base ().find (k));
+ }
+
+ ConstIterator
+ find (Key const& k) const
+ {
+ return ConstIterator (base ().find (k));
+ }
+
+ public:
+ Void
+ swap (Set<Key, Compare>& other)
+ {
+ base ().swap (other);
+ }
+ };
+ }
+}
+
+#endif // CULT_CONTAINERS_SET_HXX
diff --git a/libcult/cult/containers/stack.hxx b/libcult/cult/containers/stack.hxx
new file mode 100644
index 0000000..930bfe8
--- /dev/null
+++ b/libcult/cult/containers/stack.hxx
@@ -0,0 +1,95 @@
+// file : cult/containers/stack.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CONTAINERS_STACK_HXX
+#define CULT_CONTAINERS_STACK_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/deque.hxx>
+
+namespace Cult
+{
+ namespace Containers
+ {
+ template <typename T, typename C = Deque<T> >
+ class Stack
+ {
+ public:
+ typedef C Container;
+ typedef typename Container::Value Value;
+
+
+ public:
+ explicit
+ Stack (Container const& c = Container())
+ : c_ (c)
+ {
+ }
+
+ Boolean
+ empty () const
+ {
+ return c_.empty();
+ }
+
+ Size
+ size () const
+ {
+ return c_.size();
+ }
+
+ Value&
+ top ()
+ {
+ return c_.back();
+ }
+
+ Value const&
+ top () const
+ {
+ return c_.back();
+ }
+
+ Void
+ push (const Value& x)
+ {
+ c_.push_back(x);
+ }
+
+ Void
+ pop()
+ {
+ c_.pop_back();
+ }
+
+ protected:
+ Container c_;
+ };
+
+ /*
+ template <class T, class Container>
+ bool operator==(const stack<T, Container>& x,
+ const stack<T, Container>& y);
+ template <class T, class Container>
+ bool operator< (const stack<T, Container>& x,
+ const stack<T, Container>& y);
+ template <class T, class Container>
+ bool operator!=(const stack<T, Container>& x,
+ const stack<T, Container>& y);
+ template <class T, class Container>
+ bool operator> (const stack<T, Container>& x,
+ const stack<T, Container>& y);
+ template <class T, class Container>
+ bool operator>=(const stack<T, Container>& x,
+ const stack<T, Container>& y);
+ template <class T, class Container>
+ bool operator<=(const stack<T, Container>& x,
+ const stack<T, Container>& y);
+ */
+ }
+}
+
+#endif // CULT_CONTAINERS_STACK_HXX
diff --git a/libcult/cult/containers/vector.hxx b/libcult/cult/containers/vector.hxx
new file mode 100644
index 0000000..3a3b32f
--- /dev/null
+++ b/libcult/cult/containers/vector.hxx
@@ -0,0 +1,164 @@
+// file : cult/containers/vector.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_CONTAINERS_VECTOR_HXX
+#define CULT_CONTAINERS_VECTOR_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/iterator.hxx>
+
+#include <vector>
+
+namespace Cult
+{
+ namespace Containers
+ {
+ template <typename T>
+ class Vector: public std::vector<T>
+ {
+ typedef std::vector<T> Base;
+
+ Base&
+ base ()
+ {
+ return *this;
+ }
+
+ Base const&
+ base () const
+ {
+ return *this;
+ }
+
+ public:
+ typedef typename Base::value_type Value;
+
+ typedef typename Base::reference Reference;
+ typedef typename Base::const_reference ConstReference;
+
+ typedef typename Base::pointer Pointer;
+ typedef typename Base::const_pointer ConstPointer;
+
+
+ typedef
+ IteratorAdapter<typename Base::iterator>
+ Iterator;
+
+ typedef
+ IteratorAdapter<typename Base::const_iterator>
+ ConstIterator;
+
+
+ typedef
+ IteratorAdapter<typename Base::reverse_iterator>
+ ReverseIterator;
+
+ typedef
+ IteratorAdapter<typename Base::const_reverse_iterator>
+ ConstReverseIterator;
+
+
+ // Use Cult::Size and Cult::PtrDifference.
+ //
+ // typedef Base::size_type;
+ // typedef Base::difference_type;
+
+ public:
+ explicit
+ Vector ()
+ : Base ()
+ {
+ }
+
+ explicit
+ Vector (Size size, Value const& value = Value ())
+ : Base (size, value)
+ {
+ }
+
+ template <typename InputIterator>
+ Vector (InputIterator first, InputIterator last)
+ : Base (first, last)
+ {
+ }
+
+ Vector (Vector<Value> const& other)
+ : Base (other)
+ {
+ }
+
+ Vector<Value>&
+ operator= (Vector<Value> const& other)
+ {
+ base () = other;
+ return *this;
+ }
+
+ public:
+ Iterator
+ begin ()
+ {
+ return Iterator (base ().begin ());
+ }
+
+ Iterator
+ end ()
+ {
+ return Iterator (base ().end ());
+ }
+
+
+ ConstIterator
+ begin () const
+ {
+ return ConstIterator (base ().begin ());
+ }
+
+ ConstIterator
+ end () const
+ {
+ return ConstIterator (base ().end ());
+ }
+
+ //
+ //
+
+ ReverseIterator
+ rbegin ()
+ {
+ return ReverseIterator (base ().rbegin ());
+ }
+
+ ReverseIterator
+ rend ()
+ {
+ return ReverseIterator (base ().rend ());
+ }
+
+
+ ConstReverseIterator
+ rbegin () const
+ {
+ return ConstReverseIterator (base ().rbegin ());
+ }
+
+ ConstReverseIterator
+ rend () const
+ {
+ return ConstReverseIterator (base ().rend ());
+ }
+
+ public:
+ Void
+ swap (Vector<Value>& other)
+ {
+ base ().swap (other);
+ }
+ };
+ }
+}
+
+#endif // CULT_CONTAINERS_VECTOR_HXX
diff --git a/libcult/cult/dr/xdr/input-stream.cxx b/libcult/cult/dr/xdr/input-stream.cxx
new file mode 100644
index 0000000..1730763
--- /dev/null
+++ b/libcult/cult/dr/xdr/input-stream.cxx
@@ -0,0 +1,152 @@
+// file : cult/dr/xdr/input-stream.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/dr/xdr/input-stream.hxx>
+
+namespace Cult
+{
+ namespace DR
+ {
+ namespace XDR
+ {
+ InputStream::
+ InputStream (Shptr<Buffer> buffer)
+ : buffer_ (buffer)
+ {
+ xdrmem_create (&xdr_, buffer_->data (), buffer_->size (), XDR_DECODE);
+ }
+
+ InputStream::
+ ~InputStream ()
+ {
+ xdr_destroy (&xdr_);
+ }
+
+ InputStream& InputStream::
+ operator>> (Boolean& v)
+ {
+ bool_t b;
+
+ if (!xdr_bool (&xdr_, &b))
+ throw Extraction ();
+
+ v = b;
+
+ return *this;
+ }
+
+ InputStream& InputStream::
+ operator>> (Int8& v)
+ {
+ if (!xdr_int8_t (&xdr_, &v))
+ throw Extraction ();
+
+ return *this;
+ }
+
+ InputStream& InputStream::
+ operator>> (UnsignedInt8& v)
+ {
+ if (!xdr_uint8_t (&xdr_, &v))
+ throw Extraction ();
+
+ return *this;
+ }
+
+ InputStream& InputStream::
+ operator>> (Int16& v)
+ {
+ if (!xdr_int16_t (&xdr_, &v))
+ throw Extraction ();
+
+ return *this;
+ }
+
+ InputStream& InputStream::
+ operator>> (UnsignedInt16& v)
+ {
+ if (!xdr_uint16_t (&xdr_, &v))
+ throw Extraction ();
+
+ return *this;
+ }
+
+ InputStream& InputStream::
+ operator>> (Int32& v)
+ {
+ if (!xdr_int32_t (&xdr_, &v))
+ throw Extraction ();
+
+ return *this;
+ }
+
+ InputStream& InputStream::
+ operator>> (UnsignedInt32& v)
+ {
+ if (!xdr_uint32_t (&xdr_, &v))
+ throw Extraction ();
+
+ return *this;
+ }
+
+ InputStream& InputStream::
+ operator>> (Int64& v)
+ {
+ if (!xdr_int64_t (&xdr_, (int64_t*)&v))
+ throw Extraction ();
+
+ return *this;
+ }
+
+ InputStream& InputStream::
+ operator>> (UnsignedInt64& v)
+ {
+ if (!xdr_uint64_t (&xdr_, (uint64_t*)&v))
+ throw Extraction ();
+
+ return *this;
+ }
+
+ InputStream& InputStream::
+ operator>> (String& v)
+ {
+ UnsignedInt32 size;
+
+ if (!xdr_uint32_t (&xdr_, &size))
+ throw Extraction ();
+
+ // I dare to change the guts!
+ //
+ v.resize (size);
+
+ Char* p (const_cast<Char*> (v.data ()));
+
+ if (!xdr_opaque (&xdr_, p, size))
+ throw Extraction ();
+
+ return *this;
+ }
+
+ Void InputStream::
+ read (Buffer& buffer, Size size)
+ {
+ Size new_size (buffer.position () + size);
+
+ buffer.capacity (new_size);
+
+ if (!xdr_opaque (&xdr_, buffer.data () + buffer.position (), size))
+ throw Extraction ();
+
+ buffer.size (new_size);
+ }
+
+ Boolean InputStream::
+ eos () const
+ {
+ return xdr_getpos (&xdr_) >= buffer_->size ();
+ }
+ }
+ }
+}
diff --git a/libcult/cult/dr/xdr/input-stream.hxx b/libcult/cult/dr/xdr/input-stream.hxx
new file mode 100644
index 0000000..653b228
--- /dev/null
+++ b/libcult/cult/dr/xdr/input-stream.hxx
@@ -0,0 +1,78 @@
+// file : cult/dr/xdr/input-stream.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_DR_XDR_INPUT_STREAM_HXX
+#define CULT_DR_XDR_INPUT_STREAM_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/eh/exception.hxx>
+
+#include <cult/mm/buffer.hxx>
+
+#include <rpc/xdr.h>
+
+namespace Cult
+{
+ namespace DR
+ {
+ namespace XDR
+ {
+ struct Extraction: virtual EH::Exception {};
+
+ class InputStream: public NonCopyable
+ {
+ public:
+ InputStream (Shptr<Buffer> buffer);
+
+ ~InputStream ();
+
+ public:
+ InputStream&
+ operator>> (Boolean&);
+
+ InputStream&
+ operator>> (Int8&);
+
+ InputStream&
+ operator>> (UnsignedInt8&);
+
+ InputStream&
+ operator>> (Int16&);
+
+ InputStream&
+ operator>> (UnsignedInt16&);
+
+ InputStream&
+ operator>> (Int32&);
+
+ InputStream&
+ operator>> (UnsignedInt32&);
+
+ InputStream&
+ operator>> (Int64&);
+
+ InputStream&
+ operator>> (UnsignedInt64&);
+
+ InputStream&
+ operator>> (String&);
+
+ public:
+ Void
+ read (Buffer& buffer, Size size);
+
+ Boolean
+ eos () const;
+
+ private:
+ ::XDR xdr_;
+ Shptr<Buffer> buffer_;
+ };
+ }
+ }
+}
+
+#endif // CULT_DR_XDR_INPUT_STREAM_HXX
diff --git a/libcult/cult/dr/xdr/output-stream.cxx b/libcult/cult/dr/xdr/output-stream.cxx
new file mode 100644
index 0000000..acda64c
--- /dev/null
+++ b/libcult/cult/dr/xdr/output-stream.cxx
@@ -0,0 +1,222 @@
+// file : cult/dr/xdr/output-stream.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/dr/xdr/output-stream.hxx>
+
+namespace Cult
+{
+ namespace DR
+ {
+ namespace XDR
+ {
+ OutputStream::
+ OutputStream (Size hint)
+ : buffer_ (new Buffer (hint ? hint : 256))
+ {
+ xdrmem_create (&xdr_, buffer_->data (), ~(u_int (0)), XDR_ENCODE);
+ }
+
+
+ OutputStream::
+ ~OutputStream ()
+ {
+ xdr_destroy (&xdr_);
+ }
+
+ Shptr<Buffer> OutputStream::
+ buffer ()
+ {
+ return buffer_;
+ }
+
+ Void OutputStream::
+ ensure_space (Size size)
+ {
+ size += size % 4 ? 4 - size % 4 : 0;
+
+ Size needed (size + xdr_getpos (&xdr_));
+
+ if (needed > buffer_->capacity ())
+ {
+ Size new_size (buffer_->capacity () * 2);
+
+ if (needed > new_size)
+ new_size = needed % 8 ? 8 - new_size % 8 : 0;
+
+ if (buffer_->capacity (new_size))
+ {
+ xdr_destroy (&xdr_);
+
+ xdrmem_create (&xdr_,
+ buffer_->data () + buffer_->size (),
+ ~(u_int (0)),
+ XDR_ENCODE);
+ }
+ }
+ }
+
+ Void OutputStream::
+ update_position (Size position)
+ {
+ // Align to 4-boundary.
+ //
+ position += position % 4 ? 4 - position % 4 : 0;
+
+ buffer_->size (buffer_->size () + position);
+ }
+
+ OutputStream& OutputStream::
+ operator<< (Boolean v)
+ {
+ ensure_space (4);
+
+ bool_t b (v);
+
+ if (!xdr_bool (&xdr_, &b))
+ throw Insertion ();
+
+ update_position (4);
+ return *this;
+ }
+
+ OutputStream& OutputStream::
+ operator<< (Int8 v)
+ {
+ ensure_space (4);
+
+ if (!xdr_int8_t (&xdr_, &v))
+ throw Insertion ();
+
+ update_position (4);
+
+ return *this;
+ }
+
+ OutputStream& OutputStream::
+ operator<< (UnsignedInt8 v)
+ {
+ ensure_space (4);
+
+ if (!xdr_uint8_t (&xdr_, &v))
+ throw Insertion ();
+
+ update_position (4);
+
+ return *this;
+ }
+
+ OutputStream& OutputStream::
+ operator<< (Int16 v)
+ {
+ ensure_space (4);
+
+ if (!xdr_int16_t (&xdr_, &v))
+ throw Insertion ();
+
+ update_position (4);
+
+ return *this;
+ }
+
+ OutputStream& OutputStream::
+ operator<< (UnsignedInt16 v)
+ {
+ ensure_space (4);
+
+ if (!xdr_uint16_t (&xdr_, &v))
+ throw Insertion ();
+
+ update_position (4);
+
+ return *this;
+ }
+
+ OutputStream& OutputStream::
+ operator<< (Int32 v)
+ {
+ ensure_space (4);
+
+ if (!xdr_int32_t (&xdr_, &v))
+ throw Insertion ();
+
+ update_position (4);
+
+ return *this;
+ }
+
+ OutputStream& OutputStream::
+ operator<< (UnsignedInt32 v)
+ {
+ ensure_space (4);
+
+ if (!xdr_uint32_t (&xdr_, &v))
+ throw Insertion ();
+
+ update_position (4);
+
+ return *this;
+ }
+
+ OutputStream& OutputStream::
+ operator<< (Int64 v)
+ {
+ ensure_space (8);
+
+ if (!xdr_int64_t (&xdr_, (int64_t*)&v))
+ throw Insertion ();
+
+ update_position (8);
+
+ return *this;
+ }
+
+ OutputStream& OutputStream::
+ operator<< (UnsignedInt64 v)
+ {
+ ensure_space (8);
+
+ if (!xdr_uint64_t (&xdr_, (uint64_t*)&v))
+ throw Insertion ();
+
+ update_position (8);
+
+ return *this;
+ }
+
+ OutputStream& OutputStream::
+ operator<< (String const& v)
+ {
+ UnsignedInt32 size (v.size ());
+
+ ensure_space (4 + size);
+
+ Char* p (const_cast<Char*>(v.c_str ()));
+
+ if (!xdr_string (&xdr_, &p, size))
+ throw Insertion ();
+
+ update_position (4 + size);
+
+ return *this;
+ }
+
+ Void OutputStream::
+ write (Buffer const& buffer)
+ {
+ Size size (buffer.size () - buffer.position ());
+
+ ensure_space (size);
+
+ if (!xdr_opaque (
+ &xdr_,
+ const_cast<Char*> (buffer.data ()) + buffer.position (),
+ size))
+ throw Insertion ();
+
+ update_position (size);
+ }
+ }
+ }
+}
diff --git a/libcult/cult/dr/xdr/output-stream.hxx b/libcult/cult/dr/xdr/output-stream.hxx
new file mode 100644
index 0000000..72e0c19
--- /dev/null
+++ b/libcult/cult/dr/xdr/output-stream.hxx
@@ -0,0 +1,89 @@
+// file : cult/dr/xdr/output-stream.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_DR_XDR_OUTPUT_STREAM_HXX
+#define CULT_DR_XDR_OUTPUT_STREAM_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/eh/exception.hxx>
+
+#include <cult/mm/buffer.hxx>
+
+#include <rpc/xdr.h>
+
+namespace Cult
+{
+ namespace DR
+ {
+ namespace XDR
+ {
+ struct Insertion: virtual EH::Exception {};
+
+ //@@ I think I should use refernce to buffer instead of Shptr.
+ // To keep it simple, so to speak.
+ //
+ class OutputStream: public NonCopyable
+ {
+ public:
+ OutputStream (Size hint = 0);
+
+ ~OutputStream ();
+
+ public:
+ Shptr<Buffer>
+ buffer ();
+
+ public:
+ OutputStream&
+ operator<< (Boolean);
+
+ OutputStream&
+ operator<< (Int8);
+
+ OutputStream&
+ operator<< (UnsignedInt8);
+
+ OutputStream&
+ operator<< (Int16);
+
+ OutputStream&
+ operator<< (UnsignedInt16);
+
+ OutputStream&
+ operator<< (Int32);
+
+ OutputStream&
+ operator<< (UnsignedInt32);
+
+ OutputStream&
+ operator<< (Int64);
+
+ OutputStream&
+ operator<< (UnsignedInt64);
+
+ OutputStream&
+ operator<< (String const&);
+
+ public:
+ Void
+ write (Buffer const& buffer);
+
+ private:
+ Void
+ ensure_space (Size size);
+
+ Void
+ update_position (Size position);
+
+ private:
+ ::XDR xdr_;
+ Shptr<Buffer> buffer_;
+ };
+ }
+ }
+}
+
+#endif // CULT_DR_XDR_OUTPUT_STREAM_HXX
diff --git a/libcult/cult/eh/exception.cxx b/libcult/cult/eh/exception.cxx
new file mode 100644
index 0000000..21494cd
--- /dev/null
+++ b/libcult/cult/eh/exception.cxx
@@ -0,0 +1,27 @@
+// file : cult/eh/exception.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/eh/exception.hxx>
+
+#include <typeinfo>
+
+namespace Cult
+{
+ namespace EH
+ {
+ Char const* Exception::
+ what () const throw ()
+ {
+ try
+ {
+ return typeid (*this).name ();
+ }
+ catch (...)
+ {
+ return "";
+ }
+ }
+ }
+}
diff --git a/libcult/cult/eh/exception.hxx b/libcult/cult/eh/exception.hxx
new file mode 100644
index 0000000..266c591
--- /dev/null
+++ b/libcult/cult/eh/exception.hxx
@@ -0,0 +1,25 @@
+// file : cult/eh/exception.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_EH_EXCEPTION_HXX
+#define CULT_EH_EXCEPTION_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <exception> // std::exception
+
+namespace Cult
+{
+ namespace EH
+ {
+ struct Exception : std::exception
+ {
+ virtual Char const*
+ what () const throw ();
+ };
+ }
+}
+
+#endif // CULT_EH_EXCEPTION_HXX
diff --git a/libcult/cult/makefile b/libcult/cult/makefile
new file mode 100644
index 0000000..e4ce5ea
--- /dev/null
+++ b/libcult/cult/makefile
@@ -0,0 +1,160 @@
+# file : cult/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+$(call include,$(bld_root)/system.make)
+$(call include,$(scf_root)/configuration.make)
+
+cxx_tun := eh/exception.cxx
+
+cxx_tun += mm/new.cxx \
+ mm/counter.cxx \
+ mm/buffer.cxx
+
+cxx_tun += rtti/type-info.cxx
+
+cxx_tun += trace/log.cxx
+
+cxx_tun += cli/arguments.cxx \
+ cli/file-arguments.cxx \
+ cli/scanner.cxx \
+ cli/options.cxx \
+ cli/options-parser.cxx \
+ cli/options-spec.cxx
+
+ifeq ($(cult_threads),y)
+cxx_tun += sched/condition.cxx \
+ sched/mutex.cxx \
+ sched/spin.cxx \
+ sched/thread.cxx
+endif
+
+
+ifeq ($(cult_network),y)
+cxx_tun += os/net/address.cxx \
+ os/net/socket.cxx \
+ os/net/datagram-socket.cxx \
+ os/net/multicast-socket.cxx \
+ os/net/ipv4/address.cxx \
+ os/net/ipv4/datagram-socket.cxx \
+ os/net/ipv4/multicast-socket.cxx
+endif
+
+
+ifeq ($(cult_dr),y)
+cxx_tun += dr/xdr/input-stream.cxx \
+ dr/xdr/output-stream.cxx
+endif
+
+
+cxx_o := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_d := $(cxx_o:.o=.o.d)
+
+cult.l := $(out_base)/cult.l
+cult.l.cpp-options := $(out_base)/cult.l.cpp-options
+
+clean := $(out_base)/.clean
+
+
+# Architectures.
+#
+#
+#@@ arch can collide if src_root == out_root
+#
+
+# List of known architectures.
+#
+architectures := i386 \
+ i386/i486 \
+ i386/i486/i586 \
+ i386/i486/i586/i686 \
+ i386/i486/i586/i686/x86_64
+
+# Directories with architecture-specific code.
+#
+arch_dirs := mm
+arch := $(filter %$(host_cpu),$(architectures))
+
+r :=
+r := generic $(foreach a,$(subst /, ,$(arch)),$(eval r := $(if $r,$r/)$a)$r)
+
+sub_archs :=
+$(foreach a,$r,$(eval sub_archs := $a $(sub_archs)))
+
+#$(warning $(sub_archs))
+
+# $1 - sub-architecture dir (e.g. i386/i486)
+#
+define arch-rule
+
+arch_targets += $(foreach d,$(arch_dirs),$(out_base)/arch/$1/cult/$d/arch)
+
+$(out_base)/arch/$1/cult/%/arch: $(src_base)/%/arch/$1 | $(out_base)/arch/$1/cult/%/.
+ $(call message,using $1,ln -s $$$$< $$$$@)
+endef
+
+arch_targets :=
+$(foreach a,$(sub_archs),$(eval $(call arch-rule,$a)))
+
+
+# Build.
+#
+$(cult.l): $(cxx_o)
+
+ifeq ($(cult_threads),y)
+$(cult.l): -lpthread
+endif
+
+$(cxx_o) $(cxx_d): $(cult.l.cpp-options)
+
+$(cult.l.cpp-options): prefix := cult/ $(out_root)/
+$(cult.l.cpp-options): value := $(addprefix -I$(out_base)/arch/,$(sub_archs))\
+ -I$(out_root)\
+ -I$(src_root)
+
+$(cult.l.cpp-options): | $(arch_targets)
+
+$(call include-dep,$(cxx_d))
+
+
+# config.hxx
+#
+ifdef cult_dr
+$(out_base)/config.hxx: cult_threads := $(cult_threads)
+$(out_base)/config.hxx:
+ @echo '// file : cult/config.hxx' >$@
+ @echo '// author : automatically generated' >>$@
+ @echo '// copyright : Copyright (c) 2006-2010 Boris Kolpackov' >>$@
+ @echo '// license : GNU GPL v2; see accompanying LICENSE file' >>$@
+ @echo '#ifndef CULT_CONFIG_HXX' >>$@
+ @echo '#define CULT_CONFIG_HXX' >>$@
+ifeq ($(cult_threads),y)
+ @echo '#define CULT_THREADS' >>$@
+endif
+ @echo '#endif // CULT_CONFIG_HXX' >>$@
+endif
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(cult.l)
+
+
+# Clean.
+#
+$(clean): $(cult.l).o.clean \
+ $(cult.l.cpp-options).clean \
+ $(out_base)/cli/mapper.hxx.m4.clean \
+ $(addsuffix .cxx.clean,$(cxx_o)) \
+ $(addsuffix .cxx.clean,$(cxx_d))
+ $(call message,rm $$1,rm -f -r $$1,$(out_base)/arch)
+ $(call message,rm $$1,rm -f $$1,$(out_base)/config.hxx)
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-l.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+$(call include,$(bld_root)/m4/m4.make)
diff --git a/libcult/cult/meta/answer.hxx b/libcult/cult/meta/answer.hxx
new file mode 100644
index 0000000..402d152
--- /dev/null
+++ b/libcult/cult/meta/answer.hxx
@@ -0,0 +1,27 @@
+// file : cult/meta/answer.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_META_ANSWER_HXX
+#define CULT_META_ANSWER_HXX
+
+#include <cult/types/fundamental.hxx>
+
+namespace Cult
+{
+ namespace Meta
+ {
+ struct Yes
+ {
+ Char filling;
+ };
+
+ struct No
+ {
+ Char filling[2];
+ };
+ }
+}
+
+#endif // CULT_META_ANSWER_HXX
diff --git a/libcult/cult/meta/class-p.hxx b/libcult/cult/meta/class-p.hxx
new file mode 100644
index 0000000..6ac056d
--- /dev/null
+++ b/libcult/cult/meta/class-p.hxx
@@ -0,0 +1,33 @@
+// file : cult/meta/class-p.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_META_CLASS_HXX
+#define CULT_META_CLASS_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/meta/answer.hxx>
+
+namespace Cult
+{
+ namespace Meta
+ {
+ template <typename X>
+ class class_p
+ {
+ //@@ g++ bug 14881
+ public:
+ template <typename Y> static No test (...);
+ template <typename Y> static Yes test (Void* Y::*);
+
+ public:
+ //@@ Qualification bug fixed for g++ 3.4.0.
+ static Boolean const r =
+ sizeof (class_p<X>::template test<X> (0)) == sizeof (Yes);
+ };
+ }
+}
+
+#endif // CULT_META_CLASS_HXX
diff --git a/libcult/cult/meta/polymorphic-p.hxx b/libcult/cult/meta/polymorphic-p.hxx
new file mode 100644
index 0000000..0743de3
--- /dev/null
+++ b/libcult/cult/meta/polymorphic-p.hxx
@@ -0,0 +1,56 @@
+// file : cult/meta/polymorphic-p.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_META_POLYMORPHIC_HXX
+#define CULT_META_POLYMORPHIC_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/meta/class-p.hxx>
+#include <cult/meta/remove-cv.hxx>
+
+namespace Cult
+{
+ namespace Meta
+ {
+ template <typename CVX>
+ class polymorphic_p
+ {
+ typedef typename remove_cv<CVX>::R X;
+
+ template <typename Y, Boolean c>
+ struct impl
+ {
+ static const Boolean r = false;
+ };
+
+ template <typename Y>
+ struct impl<Y, true>
+ {
+ //@@ private
+
+ struct S1 : Y
+ {
+ S1 ();
+ };
+
+ struct S2 : Y
+ {
+ S2 ();
+
+ virtual
+ ~S2 () throw ();
+ };
+
+ static const Boolean r = sizeof (S1) == sizeof (S2);
+ };
+
+ public:
+ static const Boolean r = impl<X, class_p<X>::r>::r;
+ };
+ }
+}
+
+#endif // CULT_META_POLYMORPHIC_HXX
diff --git a/libcult/cult/meta/remove-c.hxx b/libcult/cult/meta/remove-c.hxx
new file mode 100644
index 0000000..a25382c
--- /dev/null
+++ b/libcult/cult/meta/remove-c.hxx
@@ -0,0 +1,27 @@
+// file : cult/meta/remove-c.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_META_REMOVE_C_HXX
+#define CULT_META_REMOVE_C_HXX
+
+namespace Cult
+{
+ namespace Meta
+ {
+ template <typename X>
+ struct remove_c
+ {
+ typedef X R;
+ };
+
+ template <typename X>
+ struct remove_c<X const>
+ {
+ typedef X R;
+ };
+ }
+}
+
+#endif // CULT_META_REMOVE_C_HXX
diff --git a/libcult/cult/meta/remove-cv.hxx b/libcult/cult/meta/remove-cv.hxx
new file mode 100644
index 0000000..190e393
--- /dev/null
+++ b/libcult/cult/meta/remove-cv.hxx
@@ -0,0 +1,24 @@
+// file : cult/meta/remove-cv.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_META_REMOVE_CV_HXX
+#define CULT_META_REMOVE_CV_HXX
+
+#include <cult/meta/remove-c.hxx>
+#include <cult/meta/remove-v.hxx>
+
+namespace Cult
+{
+ namespace Meta
+ {
+ template <typename X>
+ struct remove_cv
+ {
+ typedef typename remove_v<typename remove_c<X>::R>::R R;
+ };
+ }
+}
+
+#endif // CULT_META_REMOVE_CV_HXX
diff --git a/libcult/cult/meta/remove-v.hxx b/libcult/cult/meta/remove-v.hxx
new file mode 100644
index 0000000..eb6e4ee
--- /dev/null
+++ b/libcult/cult/meta/remove-v.hxx
@@ -0,0 +1,27 @@
+// file : cult/meta/remove-v.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_META_REMOVE_V_HXX
+#define CULT_META_REMOVE_V_HXX
+
+namespace Cult
+{
+ namespace Meta
+ {
+ template <typename X>
+ struct remove_v
+ {
+ typedef X R;
+ };
+
+ template <typename X>
+ struct remove_v<X volatile>
+ {
+ typedef X R;
+ };
+ }
+}
+
+#endif // CULT_META_REMOVE_V_HXX
diff --git a/libcult/cult/mm/arch/generic/counter.hxx b/libcult/cult/mm/arch/generic/counter.hxx
new file mode 100644
index 0000000..6a26759
--- /dev/null
+++ b/libcult/cult/mm/arch/generic/counter.hxx
@@ -0,0 +1,45 @@
+// file : cult/mm/arch/generic/counter.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_ARCH_GENERIC_COUNTER_HXX
+#define CULT_MM_ARCH_GENERIC_COUNTER_HXX
+
+#include <cult/types/fundamental.hxx>
+#include <cult/sched/spin.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ class Counter: public NonCopyable
+ {
+ public:
+ Counter ();
+
+ // After failure assume the counter has its old value.
+ //
+ Void
+ inc_ref ();
+
+
+ // After failure assume the counter has its new value.
+ //
+ Boolean
+ dec_ref ();
+
+
+ Size
+ count () const;
+
+ private:
+ Size value_;
+ mutable Sched::Spin spin_;
+ };
+ }
+}
+
+#include <cult/mm/arch/generic/counter.ixx>
+
+#endif // CULT_MM_ARCH_GENERIC_COUNTER_HXX
diff --git a/libcult/cult/mm/arch/generic/counter.ixx b/libcult/cult/mm/arch/generic/counter.ixx
new file mode 100644
index 0000000..648d28a
--- /dev/null
+++ b/libcult/cult/mm/arch/generic/counter.ixx
@@ -0,0 +1,47 @@
+// file : cult/mm/arch/generic/counter.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/sched/lock.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ inline
+ Counter::
+ Counter ()
+ : value_ (1)
+ {
+ }
+
+ inline
+ Void Counter::
+ inc_ref ()
+ {
+ Sched::Lock l (spin_);
+
+ ++value_;
+ }
+
+ inline
+ Boolean Counter::
+ dec_ref ()
+ {
+ Sched::Lock l (spin_);
+
+ return --value_ == 0;
+
+ }
+
+ inline
+ Size Counter::
+ count () const
+ {
+ Sched::Lock l (spin_);
+
+ return value_;
+ }
+ }
+}
diff --git a/libcult/cult/mm/arch/i386/counter.hxx b/libcult/cult/mm/arch/i386/counter.hxx
new file mode 100644
index 0000000..21f5f63
--- /dev/null
+++ b/libcult/cult/mm/arch/i386/counter.hxx
@@ -0,0 +1,43 @@
+// file : cult/mm/arch/i386/counter.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_ARCH_I386_COUNTER_HXX
+#define CULT_MM_ARCH_I386_COUNTER_HXX
+
+#include <cult/types/fundamental.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ class Counter: public NonCopyable
+ {
+ public:
+ Counter ();
+
+ // After failure assume the counter has its old value.
+ //
+ Void
+ inc_ref ();
+
+
+ // After failure assume the counter has its new value.
+ //
+ Boolean
+ dec_ref ();
+
+
+ Size
+ count () const;
+
+ private:
+ Size value_;
+ };
+ }
+}
+
+#include <cult/mm/arch/i386/counter.ixx>
+
+#endif // CULT_MM_ARCH_I386_COUNTER_HXX
diff --git a/libcult/cult/mm/arch/i386/counter.ixx b/libcult/cult/mm/arch/i386/counter.ixx
new file mode 100644
index 0000000..8279394
--- /dev/null
+++ b/libcult/cult/mm/arch/i386/counter.ixx
@@ -0,0 +1,46 @@
+// file : cult/mm/arch/i386/counter.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace MM
+ {
+ inline
+ Counter::
+ Counter ()
+ : value_ (1)
+ {
+ }
+
+ inline
+ Void Counter::
+ inc_ref ()
+ {
+ asm volatile ("lock; incl %0"
+ :"=m" (value_)
+ :"m" (value_));
+ }
+
+ inline
+ Boolean Counter::
+ dec_ref ()
+ {
+ register unsigned char r;
+
+ asm volatile("lock; decl %0; setz %1"
+ :"=m" (value_), "=rm" (r)
+ :"m" (value_));
+
+ return r != 0;
+ }
+
+ inline
+ Size Counter::
+ count () const
+ {
+ return value_;
+ }
+ }
+}
diff --git a/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.hxx b/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.hxx
new file mode 100644
index 0000000..5869b09
--- /dev/null
+++ b/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.hxx
@@ -0,0 +1,43 @@
+// file : cult/mm/arch/i386/i486/i586/i686/x86_64/counter.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_ARCH_I386_I486_I586_I686_X86_64_COUNTER_HXX
+#define CULT_MM_ARCH_I386_I486_I586_I686_X86_64_COUNTER_HXX
+
+#include <cult/types/fundamental.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ class Counter: public NonCopyable
+ {
+ public:
+ Counter ();
+
+ // After failure assume the counter has its old value.
+ //
+ Void
+ inc_ref ();
+
+
+ // After failure assume the counter has its new value.
+ //
+ Boolean
+ dec_ref ();
+
+
+ Size
+ count () const;
+
+ private:
+ Size value_;
+ };
+ }
+}
+
+#include <cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx>
+
+#endif // CULT_MM_ARCH_I386_I486_I586_I686_X86_64_COUNTER_HXX
diff --git a/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx b/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx
new file mode 100644
index 0000000..9e9e7f4
--- /dev/null
+++ b/libcult/cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx
@@ -0,0 +1,46 @@
+// file : cult/mm/arch/i386/i486/i586/i686/x86_64/counter.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace MM
+ {
+ inline
+ Counter::
+ Counter ()
+ : value_ (1)
+ {
+ }
+
+ inline
+ Void Counter::
+ inc_ref ()
+ {
+ asm volatile ("lock; incq %0"
+ :"=m" (value_)
+ :"m" (value_));
+ }
+
+ inline
+ Boolean Counter::
+ dec_ref ()
+ {
+ register unsigned char r;
+
+ asm volatile("lock; decq %0; setz %1"
+ :"=m" (value_), "=rm" (r)
+ :"m" (value_));
+
+ return r != 0;
+ }
+
+ inline
+ Size Counter::
+ count () const
+ {
+ return value_;
+ }
+ }
+}
diff --git a/libcult/cult/mm/bits/evptr.hxx b/libcult/cult/mm/bits/evptr.hxx
new file mode 100644
index 0000000..02f0b48
--- /dev/null
+++ b/libcult/cult/mm/bits/evptr.hxx
@@ -0,0 +1,379 @@
+// file : cult/mm/bits/evptr.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_BITS_EVPTR_HXX
+#define CULT_MM_BITS_EVPTR_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/meta/answer.hxx>
+
+#include <cult/mm/counter.hxx>
+#include <cult/mm/exception.hxx>
+
+#include <cassert> // assert
+
+namespace Cult
+{
+ namespace MM
+ {
+
+ //@@ Should be in mm/evptr.hxx
+ //
+ struct Clone: virtual Exception {};
+
+ template <typename X>
+ class Evptr;
+
+ namespace Bits
+ {
+ template <typename x, Evptr<x> (x::*f) () const = &x::clone>
+ struct Helper;
+
+ //@@ Should be generalized and moved to Cult::meta
+ //
+ template <typename X>
+ struct has_clone
+ {
+ template <typename y>
+ static Meta::Yes
+ test (Helper<y>*);
+
+ template <typename>
+ static Meta::No
+ test (...);
+
+ static Boolean const r = sizeof (test<X> (0)) == sizeof (Meta::Yes);
+ };
+
+ //@@ Need to incorporate tests for polymorpism and NonCopyable.
+ //
+
+ template <typename X, Boolean = has_clone<X>::r>
+ struct Cloner;
+
+ template <typename X>
+ struct Cloner<X, true>
+ {
+ static X*
+ clone (X const* cp)
+ {
+ return cp->clone ().release ();
+ }
+ };
+
+ template <typename X>
+ struct Cloner<X, false>
+ {
+ static X*
+ clone (X const*)
+ {
+ throw MM::Clone ();
+ }
+ };
+ }
+
+ namespace Bits
+ {
+ template <typename X>
+ class Transfer;
+ }
+
+ namespace Bits
+ {
+ template <typename X>
+ class EvptrBase
+ {
+ protected:
+ ~EvptrBase ()
+ {
+ free (p_ ? p_ : cp_, c_);
+ }
+
+ EvptrBase (X* p, X const* cp, Counter* c, Boolean inc = true)
+ : p_ (p), cp_ (cp), c_ (c)
+ {
+ assert (!(p_ != 0 && cp_ != 0));
+
+ if (cp_ != 0 && c_ && inc) c_->inc_ref ();
+ }
+
+ public:
+ X*
+ get () const
+ {
+ return get_ ();
+ }
+
+ X*
+ release ()
+ {
+ X* p (get_ ());
+
+ c_ = 0;
+ p_ = 0;
+ cp_ = 0;
+
+ return p;
+ }
+
+ Size
+ count () const
+ {
+ if (c_ == 0) throw NullPointer ();
+ return c_->count ();
+ }
+
+ public:
+ // Conversion to Boolean.
+ //
+ typedef X* (EvptrBase::*BooleanConvertible)() const;
+
+ operator BooleanConvertible () const
+ {
+ return c_ ? &EvptrBase::get : 0;
+ }
+
+ protected:
+ Void
+ assign (X const* cp, Counter* c)
+ {
+ if (c_ && c_ == c) throw SelfAssignment ();
+
+ free (p_ ? p_ : cp_, c_);
+
+ if (c) c->inc_ref ();
+
+ c_ = c;
+ p_ = 0;
+ cp_ = cp;
+ }
+
+ Void
+ transfer (X* p, X const* cp, Counter* c)
+ {
+ free (p_ ? p_ : cp_, c_);
+
+ c_ = c;
+ p_ = p;
+ cp_ = cp;
+ }
+
+ protected:
+ X*
+ get_ () const
+ {
+ if (c_ == 0) return 0;
+
+ assert (p_ != 0 || cp_ != 0);
+
+ if (p_ != 0)
+ {
+ if (c_->count () == 1) return p_;
+ else
+ {
+ // Convert to shared case.
+ //
+ cp_ = p_;
+ p_ = 0;
+ }
+ }
+
+ // Shared case with cloning.
+ //
+
+ // Check if we are the sole owner.
+ //
+ if (c_->count () == 1)
+ {
+ // Convert to exclusive case.
+ //
+ p_ = const_cast<X*> (cp_);
+ cp_ = 0;
+ }
+ else
+ {
+ assert (cp_ != 0);
+
+ //p_ = cp_->clone ().release ();
+
+ p_ = Cloner<X>::clone (cp_);
+
+ free (cp_, c_);
+
+ cp_ = 0;
+ c_ = locate (p_, *counted);
+ }
+
+ return p_;
+ }
+
+ static Void
+ free (X const* p, Counter* c)
+ {
+ if (c && c->dec_ref ())
+ {
+ assert (p != 0);
+ delete p;
+ }
+ }
+
+ private:
+ template <typename>
+ friend class Evptr;
+
+ template <typename>
+ friend class Transfer;
+
+ mutable X* p_;
+ mutable X const* cp_;
+ mutable Counter* c_;
+ };
+
+
+ template <typename X>
+ class EvptrBase<X const>
+ {
+ protected:
+ ~EvptrBase ()
+ {
+ free (p_ ? p_ : cp_, c_);
+ }
+
+ EvptrBase (X const* p, X const* cp, Counter* c, Boolean inc = true)
+ : p_ (p), cp_ (cp), c_ (c)
+ {
+ assert (!(p_ != 0 && cp_ != 0));
+
+ if (cp_ != 0 && c_ && inc) c_->inc_ref ();
+ }
+
+ public:
+ X const*
+ get ()
+ {
+ return get_ ();
+ }
+
+ //@@ Should clone if shared?
+ //
+ X const*
+ release ()
+ {
+ X const* p (get_ ());
+
+ c_ = 0;
+ p_ = 0;
+ cp_ = 0;
+
+ return p;
+ }
+
+ Size
+ count () const
+ {
+ if (c_ == 0) throw NullPointer ();
+ return c_->count ();
+ }
+
+ public:
+ // Conversion to Boolean.
+ //
+ typedef X const* (EvptrBase::*BooleanConvertible)() const;
+
+ operator BooleanConvertible () const
+ {
+ return c_ ? &EvptrBase::get : 0;
+ }
+
+ protected:
+ Void
+ assign (X const* cp, Counter* c)
+ {
+ if (c_ && c_ == c) throw SelfAssignment ();
+
+ free (p_ ? p_ : cp_, c_);
+
+ if (c) c->inc_ref ();
+
+ c_ = c;
+ p_ = 0;
+ cp_ = cp;
+ }
+
+ Void
+ transfer (X const* p, X const* cp, Counter* c)
+ {
+ free (p_ ? p_ : cp_, c_);
+
+ c_ = c;
+ p_ = p;
+ cp_ = cp;
+ }
+
+ protected:
+ X const*
+ get_ () const
+ {
+ return p_ ? p_ : cp_;
+ }
+
+ static Void
+ free (X const* p, Counter* c)
+ {
+ if (c && c->dec_ref ())
+ {
+ assert (p != 0);
+ delete p;
+ }
+ }
+
+ private:
+ template <typename>
+ friend class Evptr;
+
+ template <typename>
+ friend class Transfer;
+
+ mutable X const* p_;
+ mutable X const* cp_;
+ mutable Counter* c_;
+ };
+ }
+
+ namespace Bits
+ {
+ template <typename X>
+ class Transfer : protected EvptrBase<X>
+ {
+ public:
+ Transfer (Transfer<X> const& ct)
+ : EvptrBase<X> (ct.p_, ct.cp_, ct.c_, false)
+ {
+ Transfer<X>& t (const_cast<Transfer<X>&> (ct));
+
+ t.c_ = 0;
+ t.p_ = 0;
+ t.cp_ = 0;
+ }
+
+ private:
+ Transfer (X* p, X const* cp, Counter* c)
+ : EvptrBase<X> (p, cp, c, false)
+ {
+ }
+
+ template <typename>
+ friend class Evptr;
+
+ private:
+ Transfer<X>&
+ operator= (Transfer<X> const&);
+ };
+ }
+ }
+}
+
+#endif // CULT_MM_BITS_EVPTR_HXX
diff --git a/libcult/cult/mm/bits/shptr.hxx b/libcult/cult/mm/bits/shptr.hxx
new file mode 100644
index 0000000..7089c53
--- /dev/null
+++ b/libcult/cult/mm/bits/shptr.hxx
@@ -0,0 +1,85 @@
+// file : cult/mm/bits/shptr.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_BITS_SHPTR_HXX
+#define CULT_MM_BITS_SHPTR_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/mm/counter.hxx>
+#include <cult/mm/exception.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ namespace Bits
+ {
+ template <typename X>
+ class Shptr
+ {
+ protected:
+ ~Shptr ()
+ {
+ if (c_ && c_->dec_ref ()) delete p_;
+ }
+
+ Shptr (X* p, Counter* c, Boolean inc = true)
+ : p_ (p), c_ (c)
+ {
+ if (c_ && inc) c_->inc_ref ();
+ }
+
+ protected:
+ X*
+ release_ () throw ()
+ {
+ X* tmp (p_);
+
+ c_ = 0;
+ p_ = 0;
+
+ return tmp;
+ }
+
+ protected:
+ template<typename y>
+ Void
+ assign (Shptr<y> const& bp, Boolean inc = true)
+ {
+ assign (bp.p_, bp.c_, inc);
+ }
+
+ Void
+ assign (X* p, Counter* c, Boolean inc)
+ {
+ if (c_ && c_ == c) throw SelfAssignment ();
+
+ if (c_)
+ {
+ Counter* t (c_);
+ c_ = 0;
+ p_ = 0;
+ t->dec_ref ();
+ }
+
+ if (c && inc) c->inc_ref ();
+
+ p_ = p;
+ c_ = c;
+ }
+
+ protected:
+ template <typename>
+ friend class Shptr;
+
+ X* p_;
+ Counter* c_;
+ };
+ }
+ }
+}
+
+#endif // CULT_MM_BITS_SHPTR_HXX
diff --git a/libcult/cult/mm/buffer.cxx b/libcult/cult/mm/buffer.cxx
new file mode 100644
index 0000000..c3a28ff
--- /dev/null
+++ b/libcult/cult/mm/buffer.cxx
@@ -0,0 +1,140 @@
+// file : cult/mm/buffer.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/mm/buffer.hxx>
+
+#include <cstdlib> // malloc, realloc, free
+#include <cstring> // memcpy
+
+namespace Cult
+{
+ namespace MM
+ {
+ Buffer::
+ ~Buffer ()
+ {
+ std::free (b_);
+ }
+
+ Buffer::
+ Buffer (Size capacity, Size size) throw (ZeroCapacity, Bounds, BadAlloc)
+ : c_ (capacity), s_ (size), p_ (0)
+ {
+ if (c_ == 0) throw ZeroCapacity ();
+ if (s_ > c_) throw Bounds ();
+
+ b_ = std::malloc (c_);
+
+ if (b_ == 0) throw BadAlloc ();
+ }
+
+ Buffer::
+ Buffer (void const* p, size_t s)
+ : c_ (s), s_ (s), p_ (0)
+ {
+ if (c_ == 0) throw ZeroCapacity ();
+
+ b_ = std::malloc (c_);
+
+ if (b_ == 0) throw BadAlloc ();
+
+ std::memcpy (b_, p, s);
+ }
+
+
+ Buffer::
+ Buffer (Buffer const& b)
+ : c_ (b.c_), s_ (b.s_), p_ (b.p_)
+ {
+ b_ = std::malloc (c_);
+
+ if (b_ == 0) throw BadAlloc ();
+
+ std::memcpy (b_, b.b_, s_);
+ }
+/*
+ Buffer&
+ operator= (Buffer const&)
+ {
+ return *this;
+ }
+*/
+
+ // capacity
+ //
+
+ Size Buffer::
+ capacity () const throw ()
+ {
+ return c_;
+ }
+
+ Boolean Buffer::
+ capacity (Size c) throw (ZeroCapacity, Bounds, BadAlloc)
+ {
+ if (c == 0) throw ZeroCapacity ();
+ if (s_ > c) throw Bounds ();
+
+ Void* b (std::realloc (b_, c));
+
+ if (b == 0) throw BadAlloc ();
+
+ c_ = c;
+
+ if (b == b_) return false;
+
+ b_ = b;
+
+ return true;
+ }
+
+ // size
+ //
+
+ Size Buffer::
+ size () const throw ()
+ {
+ return s_;
+ }
+
+ void Buffer::
+ size (Size s) throw (Bounds)
+ {
+ if (s > c_ || p_ > s) throw Bounds ();
+
+ s_ = s;
+ }
+
+ // position
+ //
+
+ Index Buffer::
+ position () const throw ()
+ {
+ return p_;
+ }
+
+ Void Buffer::
+ position (Index p) throw (Bounds)
+ {
+ if (p > s_) throw Bounds ();
+
+ p_ = p;
+ }
+
+
+ Char const* Buffer::
+ data () const
+ {
+ return reinterpret_cast<Char const*> (b_);
+ }
+
+ Char* Buffer::
+ data ()
+ {
+ return reinterpret_cast<Char*> (b_);
+ }
+ }
+}
diff --git a/libcult/cult/mm/buffer.hxx b/libcult/cult/mm/buffer.hxx
new file mode 100644
index 0000000..d50c824
--- /dev/null
+++ b/libcult/cult/mm/buffer.hxx
@@ -0,0 +1,80 @@
+// file : cult/mm/buffer.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_BUFFER_HXX
+#define CULT_MM_BUFFER_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/mm/exception.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ //@@ why can't capacity be zero?
+ //
+
+ class Buffer
+ {
+ public:
+ struct Bounds: virtual Exception {};
+ struct ZeroCapacity: virtual Exception {};
+
+ public:
+ virtual
+ ~Buffer ();
+
+ Buffer (Size capacity, Size size = 0)
+ throw (ZeroCapacity, Bounds, BadAlloc);
+
+ Buffer (Void const*, Size size);
+
+ Buffer (Buffer const& other);
+
+ private:
+ Buffer&
+ operator= (Buffer const&);
+
+ public:
+ Size
+ capacity () const throw ();
+
+ // Returns true if the underlying buffer has been moved.
+ //
+ Boolean
+ capacity (Size capacity) throw (ZeroCapacity, Bounds, BadAlloc);
+
+ public:
+ Size
+ size () const throw ();
+
+ Void
+ size (Size size) throw (Bounds);
+
+ public:
+ Index
+ position () const throw ();
+
+ Void
+ position (Index) throw (Bounds);
+
+ public:
+ Char const*
+ data () const;
+
+ Char*
+ data ();
+
+ private:
+ Void* b_;
+ Size c_, s_, p_;
+ };
+ }
+
+ using MM::Buffer;
+}
+
+#endif // CULT_MM_BUFFER_HXX
diff --git a/libcult/cult/mm/counter.cxx b/libcult/cult/mm/counter.cxx
new file mode 100644
index 0000000..7d43e3c
--- /dev/null
+++ b/libcult/cult/mm/counter.cxx
@@ -0,0 +1,14 @@
+// file : cult/mm/counter.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/mm/counter.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ StaticPtr<Key<Counter> > counted;
+ }
+}
diff --git a/libcult/cult/mm/counter.hxx b/libcult/cult/mm/counter.hxx
new file mode 100644
index 0000000..12e1e70
--- /dev/null
+++ b/libcult/cult/mm/counter.hxx
@@ -0,0 +1,79 @@
+// file : cult/mm/counter.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_COUNTER_HXX
+#define CULT_MM_COUNTER_HXX
+
+#ifdef CULT_THREADS
+
+// Multi-threaded version is architecture-specific.
+//
+#include <cult/mm/arch/counter.hxx>
+
+#else
+
+// Single-threaded version.
+//
+
+#include <cult/types/fundamental.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ class Counter: public NonCopyable
+ {
+ public:
+ Counter ();
+
+ // After failure assume the counter has its old value.
+ //
+ Void
+ inc_ref ();
+
+
+ // After failure assume the counter has its new value.
+ //
+ Boolean
+ dec_ref ();
+
+
+ Size
+ count () const;
+
+ private:
+ Size value_;
+ };
+ }
+}
+
+#include <cult/mm/counter.ixx>
+
+#endif // CULT_THREADS
+
+
+#include <cult/mm/new.hxx>
+#include <cult/mm/static-ptr.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ extern StaticPtr<Key<Counter> > counted;
+
+
+ // Non-member inc_ref. Especially useful for messing with `this'.
+ //
+ template <typename X>
+ X*
+ inc_ref (X* p)
+ {
+ locate (p, *counted)->inc_ref ();
+ return p;
+ }
+ }
+}
+
+#endif // CULT_MM_COUNTER_HXX
diff --git a/libcult/cult/mm/counter.ixx b/libcult/cult/mm/counter.ixx
new file mode 100644
index 0000000..f807552
--- /dev/null
+++ b/libcult/cult/mm/counter.ixx
@@ -0,0 +1,38 @@
+// file : cult/mm/counter.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace MM
+ {
+ inline
+ Counter::
+ Counter ()
+ : value_ (1)
+ {
+ }
+
+ inline
+ Void Counter::
+ inc_ref ()
+ {
+ ++value_;
+ }
+
+ inline
+ Boolean Counter::
+ dec_ref ()
+ {
+ return --value_ == 0;
+ }
+
+ inline
+ Size Counter::
+ count () const
+ {
+ return value_;
+ }
+ }
+}
diff --git a/libcult/cult/mm/evptr.hxx b/libcult/cult/mm/evptr.hxx
new file mode 100644
index 0000000..ed0bd93
--- /dev/null
+++ b/libcult/cult/mm/evptr.hxx
@@ -0,0 +1,221 @@
+// file : cult/mm/evptr.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_EVPTR_HXX
+#define CULT_MM_EVPTR_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/mm/exception.hxx>
+#include <cult/mm/bits/evptr.hxx>
+
+#include <typeinfo> //@@ tmp
+
+namespace Cult
+{
+ namespace MM
+ {
+ // Leaks resource should dec_ref fail.
+ //
+ template <typename X>
+ class Evptr: public Bits::EvptrBase<X>
+ {
+ typedef Bits::EvptrBase<X> Base;
+
+ public:
+ Evptr (X* p = 0)
+ : Base (p, 0, locate (p, *counted))
+ {
+ }
+
+ Evptr (Evptr const& ep)
+ : Base (0, ep.cp_ ? ep.cp_ : ep.p_, ep.c_)
+ {
+ }
+
+ template <typename Y>
+ Evptr (Bits::Transfer<Y> const& ct)
+ : Base (ct.p_, ct.cp_, ct.c_, false)
+ {
+ Bits::Transfer<Y>& t (const_cast<Bits::Transfer<Y>&> (ct));
+
+ t.c_ = 0;
+ t.p_ = 0;
+ t.cp_ = 0;
+ }
+
+ template <typename Y>
+ Evptr (Evptr<Y> const& ep)
+ : Base (0, ep.cp_ ? ep.cp_ : ep.p_, ep.c_)
+ {
+ //@@
+ //printf ("X : %s\n", typeid (X).name ());
+ //printf ("Y : %s\n", typeid (Y).name ());
+ }
+
+ template <typename Y>
+ Evptr (Evptr<Y const> const& ep)
+ : Base (0, ep.cp_ ? ep.cp_ : ep.p_, ep.c_)
+ {
+ //@@
+ //printf ("X : %s\n", typeid (X).name ());
+ //printf ("Y : %s const\n", typeid (Y).name ());
+ }
+
+ public:
+ // After failure leaves object in destructable state.
+ //
+ Evptr&
+ operator= (Evptr const& ep)
+ {
+ this->assign (ep.cp_ ? ep.cp_ : ep.p_, ep.c_);
+
+ return *this;
+ }
+
+ template <typename Y>
+ Evptr&
+ operator= (Evptr<Y> const& ep)
+ {
+ this->assign (ep.cp_ ? ep.cp_ : ep.p_, ep.c_);
+
+ return *this;
+ }
+
+ template <typename Y>
+ Evptr&
+ operator= (Bits::Transfer<Y> const& ct)
+ {
+ Bits::Transfer<Y>& t (const_cast<Bits::Transfer<Y>&> (ct));
+
+ transfer (t.p_, t.cp_, t.c_);
+
+ t.c_ = 0;
+ t.p_ = 0;
+ t.cp_ = 0;
+
+ return *this;
+ }
+
+ protected:
+ using Base::get_;
+
+ public:
+ X*
+ operator-> () const
+ {
+ if (X* p = get_ ()) return p;
+
+ throw NullPointer ();
+ }
+
+ X&
+ operator* () const
+ {
+ if (X* p = get_ ()) return *p;
+
+ throw NullPointer ();
+ }
+
+ Bits::Transfer<X>
+ operator~ ()
+ {
+ Counter* c (c_);
+ X* p (p_);
+ X const* cp (cp_);
+
+ c_ = 0;
+ p_ = 0;
+ cp_ = 0;
+
+ return Bits::Transfer<X> (p, cp, c);
+ }
+
+ public:
+ using Base::p_;
+ using Base::cp_;
+ using Base::c_;
+
+ // Object pointed to by this becomes null.
+ //
+ template<typename Y>
+ Evptr<Y>
+ s_cast ()
+ {
+ if (p_)
+ {
+ Counter* c (c_);
+ Y* p (static_cast<Y*> (p_));
+
+
+ c_ = 0;
+ p_ = 0;
+ cp_ = 0;
+
+ return Evptr<Y> (p, 0, c);
+ }
+ else
+ {
+ Counter* c (c_);
+ Y const* cp (static_cast<Y const*> (cp_));
+
+ c_ = 0;
+ p_ = 0;
+ cp_ = 0;
+
+ return Evptr<Y> (0, cp, c);
+ }
+ }
+
+ // Object pointed to by this becomes null if dynamic_cast succeeds.
+ //
+ template<typename Y>
+ Evptr<Y>
+ d_cast ()
+ {
+ if (p_)
+ {
+ if (Y* p = dynamic_cast<Y*> (p_))
+ {
+ Counter* c (c_);
+
+ c_ = 0;
+ p_ = 0;
+ cp_ = 0;
+
+ return Evptr<Y> (p, 0, c);
+ }
+ }
+ else if (Y const* cp = dynamic_cast<Y const*> (cp_))
+ {
+ Counter* c (c_);
+
+ c_ = 0;
+ p_ = 0;
+ cp_ = 0;
+
+ return Evptr<Y> (0, cp, c);
+ }
+
+ return Evptr<Y> (0);
+ }
+
+
+ private:
+ Evptr (X* p, X const* cp, Counter* c) // for *_cast
+ : Base (p, cp, c, false)
+ {
+ }
+
+ private:
+ template <typename>
+ friend class Evptr;
+ };
+ }
+
+ using MM::Evptr;
+}
+
+#endif // CULT_MM_EVPTR_HXX
diff --git a/libcult/cult/mm/exception.hxx b/libcult/cult/mm/exception.hxx
new file mode 100644
index 0000000..38b3412
--- /dev/null
+++ b/libcult/cult/mm/exception.hxx
@@ -0,0 +1,31 @@
+// file : cult/mm/exceptions.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_EXCEPTIONS_HXX
+#define CULT_MM_EXCEPTIONS_HXX
+
+#include <cult/eh/exception.hxx>
+
+#include <new> // std::bad_alloc
+
+namespace Cult
+{
+ namespace MM
+ {
+ typedef std::bad_alloc StdBadAlloc;
+
+ struct Exception: virtual EH::Exception {};
+
+ struct BadAlloc: virtual Exception, StdBadAlloc {};
+
+ //@@ who uses this?
+ //
+ struct SelfAssignment: virtual Exception {};
+
+ struct NullPointer : virtual Exception {};
+ }
+}
+
+#endif // CULT_MM_EXCEPTIONS_HXX
diff --git a/libcult/cult/mm/new.cxx b/libcult/cult/mm/new.cxx
new file mode 100644
index 0000000..2443f1f
--- /dev/null
+++ b/libcult/cult/mm/new.cxx
@@ -0,0 +1,192 @@
+// file : cult/mm/new.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/mm/new.hxx>
+#include <cult/mm/counter.hxx>
+
+#include <cstdlib> // std::malloc, std::free
+
+#include <cult/trace/stream.hxx>
+
+namespace
+{
+ Cult::Trace::Stream&
+ tout ()
+ {
+ static Cult::Trace::Stream o ("Cult::MM", 7);
+ return o;
+ }
+}
+
+namespace Cult
+{
+ namespace MM
+ {
+ using Bits::Offset;
+
+
+ namespace
+ {
+ Void*
+ allocate (Size size, KeyList const& l) throw (StdBadAlloc)
+ {
+ Size zone_size (0);
+
+ for (KeyList::Iterator i (l.begin ()); i != l.end (); ++i)
+ {
+ zone_size += (*i)->size ();
+ }
+
+ Size map_size ((l.size () + 1) * sizeof (Offset));
+
+ //tout () << "allocate: size: " << size
+ // << " map size: " << map_size
+ // << " zone size: " << zone_size;
+
+ Char* block (reinterpret_cast<Char*> (
+ std::malloc (size + zone_size + map_size)));
+
+ Char* base (block + zone_size + map_size);
+
+ Offset* map (reinterpret_cast<Offset*> (base) - 1); // map bottom
+ Char* zone (block + zone_size); // zone bottom
+
+ //tout () << 9 << "allocate:" << '\n'
+ // << " block : " << (Void*) block << '\n'
+ // << " base : " << (Void*) base << '\n'
+ // << " map : " << (Void*) zone << '\n'
+ // << " zone : " << (Void*) block;
+
+
+ // Initialize zone map and construct services.
+ //
+ for (KeyList::Iterator i (l.begin ()); i != l.end (); ++i)
+ {
+ KeyBase const& k (**i);
+
+ zone -= k.size (); // now at the beginning of the block
+
+ try
+ {
+ k.construct (zone);
+ }
+ catch (...)
+ {
+ std::free (block);
+ throw StdBadAlloc ();
+ }
+
+ map->key = &k;
+ map->offset = base - zone;
+
+ --map;
+ }
+
+ // Last element.
+ //
+ map->key = 0;
+ map->offset = 0;
+
+ return base;
+ }
+
+ Void
+ free (Void* p) throw ()
+ {
+ Char* base (reinterpret_cast<Char*> (p));
+
+ Offset* map (reinterpret_cast<Offset*> (base) - 1); // Map bottom.
+
+ Char* block (reinterpret_cast<Char*> (map));
+
+ while (map->key != 0)
+ {
+ Char* zone (base - map->offset);
+
+ block = zone; // Last zone is the begining of the block.
+
+ map->key->destroy (zone);
+
+ --map;
+ }
+
+ //tout () << 9 << "free:" << '\n'
+ // << " block : " << (Void*) block;
+
+ std::free (block);
+ }
+ }
+ }
+}
+
+namespace Cult
+{
+ namespace MM
+ {
+ namespace Bits
+ {
+#ifdef CULT_THREADS
+ __thread
+ Block* first_ __attribute__ ((tls_model ("initial-exec"))) = 0;
+#else
+ Block* first_ = 0;
+#endif
+ }
+ }
+}
+
+using namespace Cult;
+
+Void*
+operator new (Size s) throw (MM::StdBadAlloc)
+{
+ return MM::allocate (s, *MM::counted);
+}
+
+Void*
+operator new (Size size, MM::KeyList const& list, MM::Bits::Block const& b)
+ throw (MM::StdBadAlloc)
+{
+ Void* p (MM::allocate (size, list));
+
+ const_cast<MM::Bits::Block&> (b).set (p, size);
+
+ return p;
+}
+
+Void
+operator delete (Void* p) throw ()
+{
+ if (p) MM::free (p);
+}
+
+Void
+operator delete (Void* p, Size) throw ()
+{
+ if (p) MM::free (p);
+}
+
+namespace Cult
+{
+ namespace MM
+ {
+
+ Void* ServiceAwareObject::
+ operator new (Size size, Bits::Block const& block)
+ {
+ Void* p (allocate (size, *MM::counted));
+
+ const_cast<MM::Bits::Block&> (block).set (p, size);
+
+ return p;
+ }
+
+ Void ServiceAwareObject::
+ operator delete (Void* p, Size)
+ {
+ if (p) MM::free (p);
+ }
+ }
+}
diff --git a/libcult/cult/mm/new.hxx b/libcult/cult/mm/new.hxx
new file mode 100644
index 0000000..2b815b4
--- /dev/null
+++ b/libcult/cult/mm/new.hxx
@@ -0,0 +1,297 @@
+// file : cult/mm/new.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_NEW_HXX
+#define CULT_MM_NEW_HXX
+
+#include <cult/config.hxx>
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/mm/exception.hxx>
+
+#include <cult/meta/polymorphic-p.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ class KeyBase
+ {
+ public:
+ // Returned size should be a multiple of a "perfect" size,
+ // sizeof (size_t) * 2.
+ //
+ virtual Size
+ size () const = 0;
+
+ virtual Void
+ construct (Void* p) const = 0;
+
+ virtual Void
+ destroy (Void* p) const = 0;
+
+ virtual
+ ~KeyBase ()
+ {
+ }
+ };
+
+
+ template <typename X>
+ class Key: public KeyBase, public NonCopyable
+ {
+ public:
+ Key ()
+ {
+ }
+
+ virtual Size
+ size () const
+ {
+ //@@ I can do this transparently in allocate().
+ //
+ Size align (sizeof (Size) * 2);
+ Size size (sizeof (X));
+
+ return align * (size / align + ((size % align) ? 1 : 0));
+ }
+
+ virtual Void
+ construct (Void* p) const
+ {
+ new (p) X;
+ }
+
+ virtual Void
+ destroy (Void* p) const
+ {
+ reinterpret_cast<X*> (p)->~X ();
+ }
+ };
+
+
+ struct Absent : virtual Exception {};
+
+
+ namespace Bits
+ {
+ Void*
+ locate (Void const* p, KeyBase const& k) throw (Absent);
+
+ template <typename X, Boolean poly = Meta::polymorphic_p<X>::r>
+ struct Locator;
+
+ template <typename X>
+ struct Locator<X, false>
+ {
+ static Void*
+ locate (X* p, KeyBase const& k) throw (Absent)
+ {
+ return Bits::locate (p, k);
+ }
+ };
+
+ template <typename X>
+ struct Locator<X, true>
+ {
+ static Void*
+ locate (X* p, KeyBase const& k) throw (Absent)
+ {
+ return Bits::locate (dynamic_cast<Void const*> (p), k);
+ }
+ };
+
+ // Note that this structure has a "perfect" size: sizeof (size_t) * 2.
+ // If its size is added to the properly-aligned pointer the result will
+ // still be a properly-aligned pointer.
+ //
+ struct Offset //@@ better name would be OffsetMap
+ {
+ KeyBase const* key;
+ Size offset;
+ };
+ }
+
+
+ template <typename X, typename Y>
+ inline
+ Y*
+ locate (X* p, Key<Y> const& k) throw (Absent)
+ {
+ return p ? reinterpret_cast<Y*> (Bits::Locator<X>::locate (p, k)) : 0;
+ }
+
+ class KeyList
+ {
+ public:
+ KeyList ()
+ : size_ (0)
+ {
+ }
+
+ KeyList (KeyBase const& k)
+ : size_ (1)
+ {
+ keys_[0] = &k;
+ }
+
+ friend KeyList
+ operator| (KeyList const& list, KeyBase const& key);
+
+ public:
+ typedef KeyBase const* const* Iterator;
+
+ Iterator
+ begin () const
+ {
+ return keys_;
+ }
+
+ Iterator
+ end () const
+ {
+ return &(keys_[size_]);
+ }
+
+ Size
+ size () const
+ {
+ return size_;
+ }
+
+ private:
+ KeyBase const* keys_[8];
+ Size size_;
+ };
+
+ inline KeyList
+ operator| (KeyList const& list, KeyBase const& key)
+ {
+ //@@ Need to throw on overflow.
+ //
+ KeyList r (list);
+ r.keys_[r.size_++] = &key;
+ return r;
+ }
+
+ inline KeyList
+ operator| (KeyBase const& a, KeyBase const& b)
+ {
+ return KeyList (a) | b;
+ }
+ }
+}
+
+namespace Cult
+{
+ namespace MM
+ {
+ namespace Bits
+ {
+ class Block;
+
+#ifdef CULT_THREADS
+ extern __thread
+ Block* first_ __attribute__ ((tls_model ("initial-exec")));
+#else
+ extern
+ Block* first_;
+#endif
+
+ class Block
+ {
+ public:
+ Block ()
+ {
+ }
+
+ ~Block ()
+ {
+ //@@ assert (first_ == this);
+ first_ = next_;
+ }
+
+ Void
+ set (Void* p, Size size)
+ {
+ p_ = reinterpret_cast<Char*> (p);
+ size_ = size;
+
+ next_ = first_;
+ first_ = this;
+ }
+
+ public:
+ static Void*
+ locate (Void const* p)
+ {
+ return locate (p, first_);
+ }
+
+ private:
+ static Void*
+ locate (Void const* p, Block* b)
+ {
+ if (b)
+ {
+ if (p >= b->p_ && p < b->p_ + b->size_) return b->p_;
+ else return locate (p, b->next_);
+ }
+
+ return 0;
+ }
+
+ private:
+ Char* p_;
+ Size size_;
+
+ Block* next_;
+ };
+ }
+ }
+}
+
+Cult::Void*
+operator new (Cult::Size) throw (Cult::MM::StdBadAlloc);
+
+Cult::Void*
+operator new (Cult::Size,
+ Cult::MM::KeyList const&,
+ Cult::MM::Bits::Block const& = Cult::MM::Bits::Block ())
+ throw (Cult::MM::StdBadAlloc);
+
+//@@ Need a special operator new that just allocates memory (to use in
+// static_ptr for instance).
+//
+
+Cult::Void
+operator delete (Cult::Void*) throw ();
+
+Cult::Void
+operator delete (Cult::Void*, Cult::Size) throw ();
+
+
+namespace Cult
+{
+ namespace MM
+ {
+ // Inherit from this class if you plan to access service objects
+ // from a ctor.
+ //
+ struct ServiceAwareObject
+ {
+ static Void*
+ operator new (Size s, Bits::Block const& b = Bits::Block ());
+
+ static Void
+ operator delete (Void* p, Size s);
+ };
+ }
+}
+
+#include <cult/mm/new.ixx>
+
+#endif // CULT_MM_NEW_HXX
diff --git a/libcult/cult/mm/new.ixx b/libcult/cult/mm/new.ixx
new file mode 100644
index 0000000..c3287fb
--- /dev/null
+++ b/libcult/cult/mm/new.ixx
@@ -0,0 +1,36 @@
+// file : cult/mm/new.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace MM
+ {
+ namespace Bits
+ {
+ inline
+ Void*
+ locate (Void const* p, KeyBase const& k) throw (Absent)
+ {
+ if (Void* bp = Block::locate (p)) p = bp;
+
+ Char* base (reinterpret_cast<Char*> (const_cast<Void*> (p)));
+
+ Offset* map (reinterpret_cast<Offset*> (base) - 1); // Map bottom.
+
+ while (map->key != 0)
+ {
+ if (map->key == &k)
+ {
+ return base - map->offset;
+ }
+
+ --map;
+ }
+
+ throw Absent ();
+ }
+ }
+ }
+}
diff --git a/libcult/cult/mm/shptr.hxx b/libcult/cult/mm/shptr.hxx
new file mode 100644
index 0000000..6630b1c
--- /dev/null
+++ b/libcult/cult/mm/shptr.hxx
@@ -0,0 +1,139 @@
+// file : cult/mm/Shptr.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_SHPTR_HXX
+#define CULT_MM_SHPTR_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/mm/exception.hxx>
+#include <cult/mm/bits/shptr.hxx>
+
+namespace Cult
+{
+ namespace MM
+ {
+ // Leaks resource should dec_ref fail.
+ //
+ template <typename X>
+ class Shptr : public Bits::Shptr<X>
+ {
+ typedef Bits::Shptr<X> Base;
+
+ public:
+ Shptr (X* p = 0)
+ : Base (p, locate (p, *counted), false)
+ {
+ }
+
+ Shptr (Shptr const& ap)
+ : Base (ap.p_, ap.c_)
+ {
+ }
+
+ template <typename Y>
+ Shptr (Shptr<Y> const& ap)
+ : Base (ap.p_, ap.c_)
+ {
+ }
+
+ public:
+ // After failure leaves object in destructable state.
+ //
+ Shptr&
+ operator= (Shptr const& ap)
+ {
+ this->assign (ap);
+ return *this;
+ }
+
+ template <typename Y>
+ Shptr&
+ operator= (Shptr<Y> const& ap)
+ {
+ this->assign (ap);
+ return *this;
+ }
+
+ public:
+ X*
+ operator-> () const
+ {
+ if (p_ == 0)
+ throw NullPointer ();
+
+ return p_;
+ }
+
+ X&
+ operator* () const
+ {
+ if (p_ == 0)
+ throw NullPointer ();
+
+ return *p_;
+ }
+
+ // conversion to bool
+ //
+ typedef X* (Shptr::*BooleanConvertible)() const;
+
+ operator BooleanConvertible () const throw ()
+ {
+ return p_ ? &Shptr<X>::operator-> : 0;
+ }
+
+ public:
+ X*
+ get () const throw ()
+ {
+ return p_;
+ }
+
+ X*
+ release () throw ()
+ {
+ return release_ ();
+ }
+
+ Size
+ count () const
+ {
+ if (p_ == 0)
+ throw NullPointer ();
+
+ return c_->count ();
+ }
+
+ public:
+ template<typename Y>
+ Shptr<Y>
+ d_cast () const
+ {
+ Y* p (dynamic_cast<Y*> (p_));
+ return Shptr<Y> (p, p ? c_ : 0);
+ }
+
+ private:
+ Shptr (X* p, Counter* c)
+ : Base (p, c)
+ {
+ }
+
+ template <typename>
+ friend class Shptr;
+
+ protected:
+ using Base::release_;
+
+ using Base::p_;
+ using Base::c_;
+ };
+ }
+
+ using MM::Shptr;
+}
+
+#endif // CULT_MM_SHPTR_HXX
diff --git a/libcult/cult/mm/static-ptr.hxx b/libcult/cult/mm/static-ptr.hxx
new file mode 100644
index 0000000..d3dffbd
--- /dev/null
+++ b/libcult/cult/mm/static-ptr.hxx
@@ -0,0 +1,75 @@
+// file : cult/mm/static-ptr.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_MM_STATIC_PTR_HXX
+#define CULT_MM_STATIC_PTR_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/mm/new.hxx> // operator new
+
+namespace Cult
+{
+ namespace MM
+ {
+ namespace Bits
+ {
+ struct Default {};
+ }
+
+ template <typename X, typename Id = Bits::Default>
+ class StaticPtr: public NonCopyable
+ {
+ public:
+ X&
+ operator* () const
+ {
+ return instance ();
+ }
+
+ X*
+ operator-> () const
+ {
+ return &instance ();
+ }
+
+ public:
+ StaticPtr ()
+ {
+ if (i_ == 0) i_ = instance_ ();
+ }
+
+ ~StaticPtr ()
+ {
+ // Note that we don't delete the object in order to avoid
+ // destruction order problem.
+ //
+ }
+
+ private:
+ static X&
+ instance ()
+ {
+ if (i_ == 0) i_ = instance_ ();
+
+ return *i_;
+ }
+
+ static X*
+ instance_ ()
+ {
+ static X* i = new (KeyList ()) X;
+ return i;
+ }
+
+ static X* i_;
+ };
+
+ template <typename X, typename Id>
+ X* StaticPtr<X, Id>::i_ = 0;
+ }
+}
+
+#endif // CULT_MM_STATIC_PTR_HXX
diff --git a/libcult/cult/os/exception.cxx b/libcult/cult/os/exception.cxx
new file mode 100644
index 0000000..1fd7e3b
--- /dev/null
+++ b/libcult/cult/os/exception.cxx
@@ -0,0 +1,13 @@
+// file : cult/os/exception.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/exception.hxx>
+
+namespace Cult
+{
+ namespace OS
+ {
+ }
+}
diff --git a/libcult/cult/os/exception.hxx b/libcult/cult/os/exception.hxx
new file mode 100644
index 0000000..3c4164e
--- /dev/null
+++ b/libcult/cult/os/exception.hxx
@@ -0,0 +1,46 @@
+// file : cult/os/exception.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_EXCEPTION_HXX
+#define CULT_OS_EXCEPTION_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/eh/exception.hxx>
+
+#include <errno.h>
+
+namespace Cult
+{
+ namespace OS
+ {
+ class Exception : public virtual EH::Exception
+ {
+ public:
+ Exception (Int code = error_code ()) throw ()
+ : code_ (code)
+ {
+ }
+
+ Int
+ code () const throw ()
+ {
+ return code_;
+ }
+
+ private:
+ static Int
+ error_code () throw ()
+ {
+ return errno;
+ }
+
+ private:
+ Int code_;
+ };
+ }
+}
+
+#endif // CULT_OS_EXCEPTION_HXX
diff --git a/libcult/cult/os/net/address.cxx b/libcult/cult/os/net/address.cxx
new file mode 100644
index 0000000..7860b29
--- /dev/null
+++ b/libcult/cult/os/net/address.cxx
@@ -0,0 +1,37 @@
+// file : cult/os/net/address.cxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/net/address.hxx>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ Address::
+ Address ()
+ {
+ }
+
+ Address::
+ ~Address ()
+ {
+ }
+
+ Address::
+ Address (Address const&)
+ {
+ }
+
+ Address& Address::
+ operator= (Address const&)
+ {
+ return *this;
+ }
+ }
+ }
+}
+
diff --git a/libcult/cult/os/net/address.hxx b/libcult/cult/os/net/address.hxx
new file mode 100644
index 0000000..2923ec6
--- /dev/null
+++ b/libcult/cult/os/net/address.hxx
@@ -0,0 +1,60 @@
+// file : cult/os/net/address.hxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_NET_ADDRESS_HXX
+#define CULT_OS_NET_ADDRESS_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/os/exception.hxx>
+
+#include <sys/socket.h> // sa_family_t, sockaddr
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ class Address
+ {
+ public:
+ struct Exception: virtual OS::Exception {};
+
+ struct Invalid : virtual Exception {};
+
+ public:
+ Address ();
+
+ virtual
+ ~Address ();
+
+ public:
+ //@@ need to wrap family
+ //
+ virtual sa_family_t
+ familiy () const = 0;
+
+ virtual sockaddr const*
+ raw_addr () const = 0;
+
+ virtual Size
+ raw_size () const = 0;
+
+
+ //@@ Should it be Clonable rather?
+ //
+ protected:
+ Address (Address const&);
+
+ Address&
+ operator= (Address const&);
+ };
+ }
+ }
+}
+
+
+#endif // CULT_OS_NET_ADDRESS_HXX
diff --git a/libcult/cult/os/net/datagram-socket.cxx b/libcult/cult/os/net/datagram-socket.cxx
new file mode 100644
index 0000000..b023b46
--- /dev/null
+++ b/libcult/cult/os/net/datagram-socket.cxx
@@ -0,0 +1,26 @@
+// file : cult/os/net/datagram-socket.cxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/net/datagram-socket.hxx>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ DatagramSocket::
+ DatagramSocket ()
+ {
+ }
+
+ DatagramSocket::
+ ~DatagramSocket ()
+ {
+ }
+ }
+ }
+}
+
diff --git a/libcult/cult/os/net/datagram-socket.hxx b/libcult/cult/os/net/datagram-socket.hxx
new file mode 100644
index 0000000..62d1a07
--- /dev/null
+++ b/libcult/cult/os/net/datagram-socket.hxx
@@ -0,0 +1,57 @@
+// file : cult/os/net/datagram-socket.hxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_NET_DATAGRAM_SOCKET_HXX
+#define CULT_OS_NET_DATAGRAM_SOCKET_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/os/net/address.hxx>
+#include <cult/os/net/socket.hxx>
+
+#include <sys/socket.h> // SOCK_DGRAM
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ class DatagramSocket: public virtual Socket
+ {
+ protected:
+ DatagramSocket ();
+
+ virtual
+ ~DatagramSocket ();
+
+ public:
+ virtual Int
+ type () const
+ {
+ return SOCK_DGRAM;
+ }
+
+ public:
+ virtual Size
+ send (Void const* buf, Size size, Address const& addr) = 0;
+
+ virtual Size
+ recv (Void* buf, Size size) = 0;
+
+ /*
+ virtual Boolean
+ recv (Void* buf,
+ Size size,
+ Size& received,
+ OS::Time const& timeout) = 0;
+ */
+ };
+ }
+ }
+}
+
+
+#endif // CULT_OS_NET_DATAGRAM_SOCKET_HXX
diff --git a/libcult/cult/os/net/ipv4/address.cxx b/libcult/cult/os/net/ipv4/address.cxx
new file mode 100644
index 0000000..2507ed6
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/address.cxx
@@ -0,0 +1,37 @@
+// file : cult/os/net/ipv4/address.cxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/net/ipv4/address.hxx>
+
+#include <ostream>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ std::ostream&
+ operator<< (std::ostream& os, Address const& addr)
+ {
+ char str[INET_ADDRSTRLEN];
+
+ if (inet_ntop (AF_INET,
+ &addr.addr_.sin_addr,
+ str,
+ INET_ADDRSTRLEN) == 0)
+ {
+ throw Address::Invalid ();
+ }
+
+ return os << str << ":" << addr.port ();
+ }
+ }
+ }
+ }
+}
+
diff --git a/libcult/cult/os/net/ipv4/address.hxx b/libcult/cult/os/net/ipv4/address.hxx
new file mode 100644
index 0000000..9168507
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/address.hxx
@@ -0,0 +1,143 @@
+// file : cult/os/net/ipv4/address.hxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_NET_IPV4_ADDRESS_HXX
+#define CULT_OS_NET_IPV4_ADDRESS_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/os/net/address.hxx>
+
+#include <netinet/in.h> // IPv4 types (sockaddr_in, etc)
+#include <arpa/inet.h> // hto{n,h}{s,l}, iNet_pton
+
+#include <iosfwd>
+#include <cstring> // memset
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ class Address: public Net::Address
+ {
+ public:
+ Address ()
+ {
+ std::memset (&addr_, 0, sizeof (addr_));
+ }
+
+ Address (sockaddr_in const& addr)
+ {
+ if (addr.sin_family != AF_INET)
+ throw Invalid ();
+
+ std::memset (&addr_, 0, sizeof (addr_));
+
+ addr_.sin_family = AF_INET;
+ addr_.sin_addr.s_addr = addr.sin_addr.s_addr;
+ addr_.sin_port = addr.sin_port;
+ }
+
+ Address (in_addr_t host_addr, in_port_t host_port)
+ {
+ std::memset (&addr_, 0, sizeof (addr_));
+
+ addr_.sin_family = AF_INET;
+ addr_.sin_addr.s_addr = htonl (host_addr);
+ addr_.sin_port = htons (host_port);
+ }
+
+ Address (String const& host_addr, in_port_t host_port)
+ {
+ std::memset (&addr_, 0, sizeof (addr_));
+
+ addr_.sin_family = AF_INET;
+ addr_.sin_port = htons (host_port);
+
+ if (inet_pton (AF_INET, host_addr.c_str (), &addr_.sin_addr) <= 0)
+ throw Invalid ();
+ }
+
+ public:
+ virtual sa_family_t
+ familiy () const
+ {
+ return AF_INET;
+ }
+
+ virtual sockaddr const*
+ raw_addr () const
+ {
+ return reinterpret_cast<sockaddr const*> (&addr_);
+ }
+
+ virtual Size
+ raw_size () const
+ {
+ return sizeof (addr_);
+ }
+
+ public:
+ sockaddr_in const&
+ addr () const
+ {
+ return addr_;
+ }
+
+ in_addr_t
+ ip () const
+ {
+ return ntohl (addr_.sin_addr.s_addr);
+ }
+
+ in_port_t
+ port () const
+ {
+ return ntohs (addr_.sin_port);
+ }
+
+ public:
+ friend
+ Boolean
+ operator< (Address const& x, Address const& y)
+ {
+ return (x.addr_.sin_addr.s_addr < y.addr_.sin_addr.s_addr) ||
+ ((x.addr_.sin_addr.s_addr == y.addr_.sin_addr.s_addr) &&
+ (x.addr_.sin_port < y.addr_.sin_port));
+ }
+
+ friend
+ Boolean
+ operator== (Address const& x, Address const& y)
+ {
+ return (x.addr_.sin_addr.s_addr == y.addr_.sin_addr.s_addr) &&
+ (x.addr_.sin_port == y.addr_.sin_port);
+ }
+
+ friend
+ Boolean
+ operator!= (Address const& x, Address const& y)
+ {
+ return !(x == y);
+ }
+
+ friend
+ std::ostream&
+ operator<< (std::ostream&, Address const&);
+
+ private:
+ sockaddr_in addr_;
+ };
+ }
+ }
+ }
+}
+
+
+#endif // CULT_OS_NET_IPV4_ADDRESS_HXX
diff --git a/libcult/cult/os/net/ipv4/datagram-socket.cxx b/libcult/cult/os/net/ipv4/datagram-socket.cxx
new file mode 100644
index 0000000..ce470cc
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/datagram-socket.cxx
@@ -0,0 +1,20 @@
+// file : cult/os/net/ipv4/datagram-socket.cxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/net/ipv4/datagram-socket.hxx>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ }
+ }
+ }
+}
+
diff --git a/libcult/cult/os/net/ipv4/datagram-socket.hxx b/libcult/cult/os/net/ipv4/datagram-socket.hxx
new file mode 100644
index 0000000..2aad43f
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/datagram-socket.hxx
@@ -0,0 +1,282 @@
+// file : cult/os/net/ipv4/datagram-socket.hxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_NET_IPV4_DATAGRAM_SOCKET_HXX
+#define CULT_OS_NET_IPV4_DATAGRAM_SOCKET_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/os/net/address.hxx>
+#include <cult/os/net/datagram-socket.hxx>
+#include <cult/os/net/ipv4/address.hxx>
+
+#include <unistd.h> // close
+#include <sys/socket.h> // socket, bind, sendto, revcfrom
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ class DatagramSocket: public virtual Net::DatagramSocket
+ {
+ public:
+ virtual
+ ~DatagramSocket ()
+ {
+ ::close (sock_);
+ }
+
+ DatagramSocket ()
+ {
+ sock_ = ::socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+ if (sock_ == -1)
+ throw Exception (); //@@
+ }
+
+ DatagramSocket (Address const& addr)
+ {
+ sock_ = ::socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+ if (sock_ == -1)
+ throw Exception (); //@@
+
+ if (::bind (sock_, addr.raw_addr (), addr.raw_size ()) == -1)
+ throw Exception (); //@@
+ }
+
+ public:
+ virtual sa_family_t
+ familiy () const
+ {
+ return AF_INET;
+ }
+
+ virtual Int
+ protocol () const
+ {
+ return IPPROTO_UDP;
+ }
+
+ // Options.
+ //
+ public:
+ Size
+ recv_buffer_size () const
+ {
+ Int r;
+ socklen_t s (sizeof (r));
+
+ if (::getsockopt (sock_,
+ SOL_SOCKET,
+ SO_RCVBUF,
+ &r,
+ &s) == -1)
+ {
+ throw Exception (); //@@
+ }
+
+ return static_cast<Size> (r);
+ }
+
+ Void
+ recv_buffer_size (Size size)
+ {
+ Int r (static_cast<Int> (size));
+
+ if (::setsockopt (sock_,
+ SOL_SOCKET,
+ SO_RCVBUF,
+ &r,
+ sizeof (r)) == -1)
+ {
+ throw Exception ();
+ }
+ }
+
+ Size
+ send_buffer_size () const
+ {
+ Int r;
+ socklen_t s (sizeof (r));
+
+ if (::getsockopt (sock_,
+ SOL_SOCKET,
+ SO_SNDBUF,
+ &r,
+ &s) == -1)
+ {
+ throw Exception ();
+ }
+
+ return static_cast<Size> (r);
+ }
+
+ void
+ send_buffer_size (Size size)
+ {
+ Int r (static_cast<Int> (size));
+
+ if (::setsockopt (sock_,
+ SOL_SOCKET,
+ SO_SNDBUF,
+ &r,
+ sizeof (r)) == -1)
+ {
+ throw Exception ();
+ }
+ }
+
+ public:
+ Void
+ connect (Address const& addr)
+ {
+ if (::connect (sock_, addr.raw_addr (), addr.raw_size ()) == -1)
+ throw Exception ();
+ }
+
+ Address
+ address () const
+ {
+ sockaddr_in raw_addr;
+ socklen_t raw_size (sizeof (raw_addr));
+
+ if (::getsockname (sock_,
+ reinterpret_cast<sockaddr*> (&raw_addr),
+ &raw_size) == -1)
+ {
+ throw Exception ();
+ }
+
+ return Address (raw_addr);
+ }
+
+
+ public:
+ virtual Size
+ send (Void const* buf, Size size, Net::Address const& addr)
+ {
+ if (addr.familiy () != familiy ())
+ throw InvalidAddress ();
+
+ return send (buf, size, dynamic_cast<Address const&> (addr));
+ }
+
+ virtual Size
+ send (Void const* buf, Size size, Address const& addr)
+ {
+ ssize_t n (::sendto (sock_,
+ buf,
+ size,
+ 0,
+ addr.raw_addr (),
+ addr.raw_size ()));
+
+ if (n == -1)
+ throw Exception ();
+
+ return static_cast<Size> (n);
+ }
+
+ virtual Size
+ recv (Void* buf, Size size)
+ {
+ ssize_t n (::recvfrom (sock_, buf, size, 0, 0, 0));
+
+ if (n == -1)
+ throw Exception ();
+
+ return static_cast<Size> (n);
+ }
+
+ virtual Size
+ recv (Void* buf, Size size, Address& addr)
+ {
+ sockaddr_in raw_addr;
+ socklen_t raw_size (sizeof (raw_addr));
+
+ ssize_t n (::recvfrom (sock_,
+ buf,
+ size,
+ 0,
+ reinterpret_cast<sockaddr*> (&raw_addr),
+ &raw_size));
+
+ if (n == -1)
+ throw Exception ();
+
+ addr = Address (raw_addr);
+
+ return static_cast<Size> (n);
+ }
+
+ virtual Size
+ peek (Void* buf, Size size, Address& addr)
+ {
+ sockaddr_in raw_addr;
+ socklen_t raw_size (sizeof (raw_addr));
+
+ ssize_t n (::recvfrom (sock_,
+ buf,
+ size,
+ MSG_PEEK,
+ reinterpret_cast<sockaddr*> (&raw_addr),
+ &raw_size));
+
+ if (n == -1)
+ throw Exception ();
+
+ addr = Address (raw_addr);
+
+ return static_cast<Size> (n);
+ }
+
+ /*
+ virtual Boolean
+ recv (Void* buf,
+ Size size,
+ Size& received,
+ OS::Time const& timeout)
+ {
+ fd_set r,e;
+
+ FD_ZERO (&r);
+ FD_ZERO (&e);
+
+ FD_SET (sock_, &r);
+ FD_SET (sock_, &e);
+
+ int n = ::pselect (sock_ + 1, &r, 0, &e, &timeout.timespec (), 0);
+
+ if (n > 0)
+ {
+ recv_size = recv (buf, buf_size);
+ return true;
+ }
+ else if (n == 0) // timeout
+ {
+ return false;
+ }
+ else
+ {
+ throw Failure ("pselect");
+ }
+ }
+ */
+
+ protected:
+ Int sock_;
+ };
+ }
+ }
+ }
+}
+
+
+#endif // CULT_OS_NET_IPV4_DATAGRAM_SOCKET_HXX
diff --git a/libcult/cult/os/net/ipv4/multicast-socket.cxx b/libcult/cult/os/net/ipv4/multicast-socket.cxx
new file mode 100644
index 0000000..1431adc
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/multicast-socket.cxx
@@ -0,0 +1,19 @@
+// file : cult/os/net/ipv4/multicast-socket.cxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/net/ipv4/multicast-socket.hxx>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ }
+ }
+ }
+}
diff --git a/libcult/cult/os/net/ipv4/multicast-socket.hxx b/libcult/cult/os/net/ipv4/multicast-socket.hxx
new file mode 100644
index 0000000..70207a3
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/multicast-socket.hxx
@@ -0,0 +1,133 @@
+// file : cult/os/net/ipv4/multicast-socket.hxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_NET_IPV4_MULTICAST_SOCKET_HXX
+#define CULT_OS_NET_IPV4_MULTICAST_SOCKET_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/os/net/address.hxx>
+#include <cult/os/net/multicast-socket.hxx>
+#include <cult/os/net/ipv4/address.hxx>
+#include <cult/os/net/ipv4/datagram-socket.hxx>
+
+#include <cstring> // memcpy
+#include <sys/socket.h> // bind, setsockopt
+#include <arpa/inet.h> // htonl
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ //@@ Add MulticastAddress (with proper checks)?
+ //
+
+ class MulticastSocket : public virtual Net::MulticastSocket,
+ public virtual DatagramSocket
+ {
+ public:
+ virtual
+ ~MulticastSocket ()
+ {
+ }
+
+ public:
+ MulticastSocket (Boolean loop = true, UnsignedShort ttl = 1)
+ {
+ unsigned char ttl_ (static_cast<unsigned char> (ttl));
+
+ {
+ Int flag (1);
+
+ if (::setsockopt (sock_,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ &flag,
+ sizeof (flag)) == -1)
+ {
+ throw Exception ();
+ }
+ }
+
+ if (ttl != 1)
+ {
+ if (::setsockopt (sock_,
+ IPPROTO_IP,
+ IP_MULTICAST_TTL,
+ &ttl_,
+ sizeof (ttl_)) == -1)
+ {
+ throw Exception ();
+ }
+ }
+
+ if (!loop)
+ {
+ unsigned char flag (0);
+
+ if (::setsockopt (sock_,
+ IPPROTO_IP,
+ IP_MULTICAST_LOOP,
+ &flag,
+ sizeof (flag)) == -1)
+ {
+ throw Exception ();
+ }
+ }
+
+ }
+
+ public:
+ virtual Void
+ join (Net::Address const& addr)
+ {
+ if (addr.familiy () != familiy ())
+ throw InvalidAddress ();
+
+ join (dynamic_cast<Address const&> (addr));
+ }
+
+ virtual Void
+ join (Address const& addr)
+ {
+ ip_mreq mreq;
+
+ std::memcpy (&mreq.imr_multiaddr,
+ &addr.addr ().sin_addr,
+ sizeof (in_addr));
+
+ mreq.imr_interface.s_addr = htonl (INADDR_ANY);
+
+ if (::setsockopt (sock_,
+ IPPROTO_IP,
+ IP_ADD_MEMBERSHIP,
+ &mreq,
+ sizeof (mreq)) == -1)
+ {
+ throw Exception ();
+ }
+
+ if (::bind (sock_, addr.raw_addr (), addr.raw_size ()) == -1)
+ throw Exception ();
+ }
+
+ virtual Void
+ leave ()
+ {
+ //@@ TODO
+ abort ();
+ }
+ };
+ }
+ }
+ }
+}
+
+
+#endif // CULT_OS_NET_IPV4_MULTICAST_SOCKET_HXX
diff --git a/libcult/cult/os/net/multicast-socket.cxx b/libcult/cult/os/net/multicast-socket.cxx
new file mode 100644
index 0000000..64710cf
--- /dev/null
+++ b/libcult/cult/os/net/multicast-socket.cxx
@@ -0,0 +1,26 @@
+// file : cult/os/net/multicast-socket.cxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/net/multicast-socket.hxx>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ MulticastSocket::
+ MulticastSocket ()
+ {
+ }
+
+ MulticastSocket::
+ ~MulticastSocket ()
+ {
+ }
+ }
+ }
+}
+
diff --git a/libcult/cult/os/net/multicast-socket.hxx b/libcult/cult/os/net/multicast-socket.hxx
new file mode 100644
index 0000000..7aeff74
--- /dev/null
+++ b/libcult/cult/os/net/multicast-socket.hxx
@@ -0,0 +1,40 @@
+// file : cult/os/net/multicast-socket.hxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_NET_MULTICAST_SOCKET_HXX
+#define CULT_OS_NET_MULTICAST_SOCKET_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/os/net/address.hxx>
+#include <cult/os/net/datagram-socket.hxx>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ class MulticastSocket : public virtual DatagramSocket
+ {
+ protected:
+ MulticastSocket ();
+
+ virtual
+ ~MulticastSocket ();
+
+ public:
+ virtual Void
+ join (Address const& addr) = 0;
+
+ virtual Void
+ leave () = 0;
+ };
+ }
+ }
+}
+
+
+#endif // CULT_OS_NET_MULTICAST_SOCKET_HXX
diff --git a/libcult/cult/os/net/socket.cxx b/libcult/cult/os/net/socket.cxx
new file mode 100644
index 0000000..bd9969c
--- /dev/null
+++ b/libcult/cult/os/net/socket.cxx
@@ -0,0 +1,26 @@
+// file : cult/os/net/socket.cxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/net/socket.hxx>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ Socket::
+ Socket ()
+ {
+ }
+
+ Socket::
+ ~Socket ()
+ {
+ }
+ }
+ }
+}
+
diff --git a/libcult/cult/os/net/socket.hxx b/libcult/cult/os/net/socket.hxx
new file mode 100644
index 0000000..a471186
--- /dev/null
+++ b/libcult/cult/os/net/socket.hxx
@@ -0,0 +1,54 @@
+// file : cult/os/net/socket.hxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_NET_SOCKET_HXX
+#define CULT_OS_NET_SOCKET_HXX
+
+#include <cult/types.hxx>
+#include <cult/os/exception.hxx>
+
+#include <sys/socket.h> // sa_family_t
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ class Socket: public NonCopyable
+ {
+ public:
+ struct Exception : virtual OS::Exception {};
+
+ struct InvalidAddress : virtual Exception {};
+
+ protected:
+ Socket ();
+
+ virtual
+ ~Socket ();
+
+ public:
+ // AF_INET, AF_INET6, etc.
+ //
+ virtual sa_family_t
+ familiy () const = 0;
+
+ // SOCK_DGRAM, SOCK_STREAM, etc.
+ //
+ virtual Int
+ type () const = 0;
+
+ // IPPROTO_UDP, IPPROTO_TCP, IPPROTO_SCTP, etc.
+ //
+ virtual Int
+ protocol () const = 0;
+ };
+ }
+ }
+}
+
+
+#endif // CULT_OS_NET_SOCKET_HXX
diff --git a/libcult/cult/rtti/type-id.hxx b/libcult/cult/rtti/type-id.hxx
new file mode 100644
index 0000000..21494b1
--- /dev/null
+++ b/libcult/cult/rtti/type-id.hxx
@@ -0,0 +1,52 @@
+// file : cult/rtti/type-id.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_RTTI_TYPE_ID_HXX
+#define CULT_RTTI_TYPE_ID_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <typeinfo> // std::type_info
+
+namespace Cult
+{
+ namespace RTTI
+ {
+ class TypeId
+ {
+ public:
+ template<typename X>
+ TypeId (X const volatile&);
+
+ TypeId (std::type_info const&);
+
+ public:
+ Char const*
+ name () const;
+
+ friend Boolean
+ operator== (TypeId const&, TypeId const&);
+
+ friend Boolean
+ operator!= (TypeId const&, TypeId const&);
+
+ friend Boolean
+ operator< (TypeId const&, TypeId const&);
+
+ /*
+ friend std::ostream&
+ operator << (std::ostream& os, TypeId const& t);
+ */
+
+ private:
+ std::type_info const* ti_;
+ };
+ }
+}
+
+#include <cult/rtti/type-id.ixx>
+#include <cult/rtti/type-id.txx>
+
+#endif // CULT_RTTI_TYPE_ID_HXX
diff --git a/libcult/cult/rtti/type-id.ixx b/libcult/cult/rtti/type-id.ixx
new file mode 100644
index 0000000..cc77d5f
--- /dev/null
+++ b/libcult/cult/rtti/type-id.ixx
@@ -0,0 +1,45 @@
+// file : cult/rtti/type-id.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace RTTI
+ {
+ inline
+ TypeId::
+ TypeId (std::type_info const& ti)
+ : ti_ (&ti)
+ {
+ }
+
+ inline
+ Char const* TypeId::
+ name () const
+ {
+ return ti_->name ();
+ }
+
+ inline
+ Boolean
+ operator== (TypeId const& x, TypeId const& y)
+ {
+ return *x.ti_ == *y.ti_;
+ }
+
+ inline
+ Boolean
+ operator!= (TypeId const& x, TypeId const& y)
+ {
+ return *x.ti_ != *y.ti_;
+ }
+
+ inline
+ Boolean
+ operator< (TypeId const& x, TypeId const& y)
+ {
+ return x.ti_->before (*y.ti_);
+ }
+ }
+}
diff --git a/libcult/cult/rtti/type-id.txx b/libcult/cult/rtti/type-id.txx
new file mode 100644
index 0000000..4fd771a
--- /dev/null
+++ b/libcult/cult/rtti/type-id.txx
@@ -0,0 +1,18 @@
+// file : cult/rtti/type-id.txx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace RTTI
+ {
+ template <typename X>
+ inline
+ TypeId::
+ TypeId (X const volatile& x)
+ : ti_ (&typeid (x))
+ {
+ }
+ }
+}
diff --git a/libcult/cult/rtti/type-info.cxx b/libcult/cult/rtti/type-info.cxx
new file mode 100644
index 0000000..5bc4040
--- /dev/null
+++ b/libcult/cult/rtti/type-info.cxx
@@ -0,0 +1,42 @@
+// file : cult/rtti/type-info.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/rtti/type-info.hxx>
+
+#include <cult/mm/static-ptr.hxx>
+
+#include <cult/containers/map.hxx>
+
+namespace Cult
+{
+ namespace RTTI
+ {
+ Access const Access::private_ (Access::private__);
+ Access const Access::protected_ (Access::protected__);
+ Access const Access::public_ (Access::public__);
+
+ typedef
+ Containers::Map<TypeId, TypeInfo>
+ TypeInfoMap;
+
+ static MM::StaticPtr<TypeInfoMap> map_;
+
+ TypeInfo const&
+ lookup (TypeId const& type_id)
+ {
+ TypeInfoMap::ConstIterator i (map_->find (type_id));
+
+ if (i == map_->end ()) throw NoInfo ();
+
+ return i->second;
+ }
+
+ Void
+ insert (TypeInfo const& type_info)
+ {
+ map_->insert (TypeInfoMap::Pair (type_info.type_id (), type_info));
+ }
+ }
+}
diff --git a/libcult/cult/rtti/type-info.hxx b/libcult/cult/rtti/type-info.hxx
new file mode 100644
index 0000000..dce4923
--- /dev/null
+++ b/libcult/cult/rtti/type-info.hxx
@@ -0,0 +1,147 @@
+// file : cult/rtti/type-info.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_RTTI_TYPE_INFO_HXX
+#define CULT_RTTI_TYPE_INFO_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/rtti/type-id.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <typeinfo> // std::type_info
+
+namespace Cult
+{
+ namespace RTTI
+ {
+ //
+ //
+ //
+ class Access
+ {
+ public:
+ static Access const private_, protected_, public_;
+
+ friend Boolean
+ operator== (Access const& a, Access const& b)
+ {
+ return a.v_ == b.v_;
+ }
+
+ friend Boolean
+ operator!= (Access const& a, Access const& b)
+ {
+ return a.v_ != b.v_;
+ }
+
+ private:
+ enum Value { private__, protected__, public__ } v_;
+
+ Access (Value v)
+ : v_ (v)
+ {
+ }
+ };
+
+ //
+ //
+ class TypeInfo;
+
+
+ //
+ //
+ class BaseInfo
+ {
+ public:
+ BaseInfo (Access access, Boolean virtual_, TypeId const& type_id);
+
+ public:
+ TypeInfo const&
+ type_info () const;
+
+ Access
+ access () const;
+
+ Boolean
+ virtual_ () const;
+
+ private:
+ Access access_;
+ Boolean virtual__;
+ TypeId type_id_;
+ mutable TypeInfo const* type_info_;
+ };
+
+
+ //
+ //
+ class TypeInfo
+ {
+ typedef Containers::Vector<BaseInfo> BaseInfoList;
+
+ public:
+ typedef
+ BaseInfoList::ConstIterator
+ BaseIterator;
+
+ public:
+ TypeInfo (TypeId const& type_id);
+
+ TypeId
+ type_id () const;
+
+ BaseIterator
+ begin_base () const;
+
+ BaseIterator
+ end_base () const;
+
+ Void
+ add_base (Access access, Boolean virtual_, TypeId const& type_id);
+
+ private:
+ TypeId type_id_;
+ BaseInfoList base_list_;
+ };
+
+
+ //
+ //
+ class NoInfo {};
+
+ TypeInfo const&
+ lookup (TypeId const& type_id);
+
+ inline
+ TypeInfo const&
+ lookup (std::type_info const& type_info)
+ {
+ return lookup (TypeId (type_info));
+ }
+
+ template<typename X>
+ TypeInfo const&
+ lookup (X const& x)
+ {
+ return lookup (typeid (x));
+ }
+
+ template<typename X>
+ TypeInfo const&
+ lookup ()
+ {
+ return lookup (typeid (X));
+ }
+
+ Void
+ insert (TypeInfo const&);
+ }
+}
+
+#include <cult/rtti/type-info.ixx>
+
+#endif // CULT_RTTI_TYPE_INFO_HXX
diff --git a/libcult/cult/rtti/type-info.ixx b/libcult/cult/rtti/type-info.ixx
new file mode 100644
index 0000000..f96ad6c
--- /dev/null
+++ b/libcult/cult/rtti/type-info.ixx
@@ -0,0 +1,87 @@
+// file : cult/rtti/type-info.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace RTTI
+ {
+ // BaseInfo
+ //
+
+ inline
+ BaseInfo::
+ BaseInfo (Access access, Boolean virtual_, TypeId const& type_id)
+ : access_ (access),
+ virtual__ (virtual_),
+ type_id_ (type_id),
+ type_info_ (0)
+ {
+ }
+
+ inline
+ TypeInfo const& BaseInfo::
+ type_info () const
+ {
+ if (type_info_ == 0) type_info_ = &(lookup (type_id_));
+
+ return *type_info_;
+ }
+
+
+ inline
+ Access BaseInfo::
+ access () const
+ {
+ return access_;
+ }
+
+ inline
+ Boolean BaseInfo::
+ virtual_ () const
+ {
+ return virtual__;
+ }
+
+
+ // TypeInfo
+ //
+
+ inline
+ TypeInfo::
+ TypeInfo (TypeId const& type_id)
+ : type_id_ (type_id)
+ {
+ }
+
+ inline
+ TypeId TypeInfo::
+ type_id () const
+ {
+ return type_id_;
+ }
+
+ inline
+ TypeInfo::BaseIterator TypeInfo::
+ begin_base () const
+ {
+ return base_list_.begin ();
+ }
+
+
+ inline
+ TypeInfo::BaseIterator TypeInfo::
+ end_base () const
+ {
+ return base_list_.end ();
+ }
+
+ inline
+ Void TypeInfo::
+ add_base (Access access, Boolean virtual_, TypeId const& type_id)
+ {
+ base_list_.push_back (BaseInfo (access, virtual_, type_id));
+ }
+ }
+}
diff --git a/libcult/cult/sched/condition.cxx b/libcult/cult/sched/condition.cxx
new file mode 100644
index 0000000..5f547c8
--- /dev/null
+++ b/libcult/cult/sched/condition.cxx
@@ -0,0 +1,49 @@
+// file : cult/sched/condition.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/sched/condition.hxx>
+#include <cult/sched/exception.hxx>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ Condition::
+ ~Condition ()
+ {
+ if (Int e = pthread_cond_destroy (&cond_))
+ throw Implementation (e);
+ }
+
+ Condition::
+ Condition (Mutex& mutex)
+ : mutex_ (mutex)
+ {
+ if (Int e = pthread_cond_init (&cond_, 0))
+ throw Implementation (e);
+ }
+
+ Void Condition::
+ signal ()
+ {
+ if (Int e = pthread_cond_signal (&cond_))
+ throw Implementation (e);
+ }
+
+ Void Condition::
+ broadcast ()
+ {
+ if (Int e = pthread_cond_broadcast (&cond_))
+ throw Implementation (e);
+ }
+
+ Void Condition::
+ wait ()
+ {
+ if (Int e = pthread_cond_wait (&cond_, &mutex_.mutex_))
+ throw Implementation (e);
+ }
+ }
+}
diff --git a/libcult/cult/sched/condition.hxx b/libcult/cult/sched/condition.hxx
new file mode 100644
index 0000000..b1a0f30
--- /dev/null
+++ b/libcult/cult/sched/condition.hxx
@@ -0,0 +1,42 @@
+// file : cult/sched/condition.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_SCHED_CONDITION_HXX
+#define CULT_SCHED_CONDITION_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/sched/mutex.hxx>
+
+#include <pthread.h>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ class Condition: public NonCopyable
+ {
+ public:
+ ~Condition ();
+
+ Condition (Mutex& mutex);
+
+ Void
+ signal ();
+
+ Void
+ broadcast ();
+
+ Void
+ wait ();
+
+ private:
+ Mutex& mutex_;
+ pthread_cond_t cond_;
+ };
+ }
+}
+
+#endif // CULT_SCHED_CONDITION_HXX
diff --git a/libcult/cult/sched/exception.hxx b/libcult/cult/sched/exception.hxx
new file mode 100644
index 0000000..3fa6e5f
--- /dev/null
+++ b/libcult/cult/sched/exception.hxx
@@ -0,0 +1,30 @@
+// file : cult/sched/exception.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_SCHED_EXCEPTION_HXX
+#define CULT_SCHED_EXCEPTION_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/eh/exception.hxx>
+#include <cult/os/exception.hxx>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ struct Exception: virtual EH::Exception {};
+
+ struct Implementation: virtual Exception, virtual OS::Exception
+ {
+ Implementation (Int code) throw ()
+ : OS::Exception (code)
+ {
+ }
+ };
+ }
+}
+
+#endif // CULT_SCHED_EXCEPTION_HXX
diff --git a/libcult/cult/sched/lock.cxx b/libcult/cult/sched/lock.cxx
new file mode 100644
index 0000000..853d9b0
--- /dev/null
+++ b/libcult/cult/sched/lock.cxx
@@ -0,0 +1,13 @@
+// file : cult/sched/lock.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/sched/lock.hxx>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ }
+}
diff --git a/libcult/cult/sched/lock.hxx b/libcult/cult/sched/lock.hxx
new file mode 100644
index 0000000..1ecf3fb
--- /dev/null
+++ b/libcult/cult/sched/lock.hxx
@@ -0,0 +1,58 @@
+// file : cult/sched/lock.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_SCHED_LOCK_HXX
+#define CULT_SCHED_LOCK_HXX
+
+#include <cult/types/fundamental.hxx>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ class Lock: public NonCopyable
+ {
+ public:
+ ~Lock ()
+ {
+ unlock ();
+ }
+
+ template <typename X>
+ Lock (X& x)
+ : x_ (reinterpret_cast<Void*>(&x)),
+ unlock_ (&unlock<X>),
+ locked_ (true)
+ {
+ x.lock ();
+ }
+
+ Void
+ unlock ()
+ {
+ if (locked_)
+ {
+ unlock_ (x_);
+ locked_ = false;
+ }
+ }
+
+ private:
+ template <typename X>
+ static Void
+ unlock (Void* p)
+ {
+ reinterpret_cast<X*> (p)->unlock ();
+ }
+
+ private:
+ Void* x_;
+ Void (*unlock_) (Void*);
+ Boolean locked_;
+ };
+ }
+}
+
+#endif // CULT_SCHED_LOCK_HXX
diff --git a/libcult/cult/sched/mutex.cxx b/libcult/cult/sched/mutex.cxx
new file mode 100644
index 0000000..9667a67
--- /dev/null
+++ b/libcult/cult/sched/mutex.cxx
@@ -0,0 +1,54 @@
+// file : cult/sched/mutex.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/sched/mutex.hxx>
+#include <cult/sched/exception.hxx>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ Mutex::
+ ~Mutex ()
+ {
+ if (Int e = pthread_mutex_destroy (&mutex_))
+ throw Implementation (e);
+ }
+
+ Mutex::
+ Mutex ()
+ {
+ if (Int e = pthread_mutex_init (&mutex_, 0))
+ throw Implementation (e);
+ }
+
+ Void Mutex::
+ lock ()
+ {
+ if (Int e = pthread_mutex_lock (&mutex_))
+ throw Implementation (e);
+ }
+
+ Boolean Mutex::
+ try_lock ()
+ {
+ Int e (pthread_mutex_trylock (&mutex_));
+
+ switch (e)
+ {
+ case 0: return true;
+ case EBUSY: return false;
+ default: throw Implementation (e);
+ }
+ }
+
+ Void Mutex::
+ unlock ()
+ {
+ if (Int e = pthread_mutex_unlock (&mutex_))
+ throw Implementation (e);
+ }
+ }
+}
diff --git a/libcult/cult/sched/mutex.hxx b/libcult/cult/sched/mutex.hxx
new file mode 100644
index 0000000..0c6daee
--- /dev/null
+++ b/libcult/cult/sched/mutex.hxx
@@ -0,0 +1,41 @@
+// file : cult/sched/mutex.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_SCHED_MUTEX_HXX
+#define CULT_SCHED_MUTEX_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <pthread.h>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ class Mutex: public NonCopyable
+ {
+ public:
+ ~Mutex ();
+
+ Mutex ();
+
+ Void
+ lock ();
+
+ Boolean
+ try_lock ();
+
+ Void
+ unlock ();
+
+ private:
+ friend class Condition;
+
+ pthread_mutex_t mutex_;
+ };
+ }
+}
+
+#endif // CULT_SCHED_MUTEX_HXX
diff --git a/libcult/cult/sched/spin.cxx b/libcult/cult/sched/spin.cxx
new file mode 100644
index 0000000..54df7ce
--- /dev/null
+++ b/libcult/cult/sched/spin.cxx
@@ -0,0 +1,28 @@
+// file : cult/sched/spin.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/sched/spin.hxx>
+#include <cult/sched/exception.hxx>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ Spin::
+ ~Spin ()
+ {
+ if (Int e = pthread_spin_destroy (&spin_))
+ throw Implementation (e);
+ }
+
+ Spin::
+ Spin ()
+ {
+ if (Int e = pthread_spin_init (&spin_, PTHREAD_PROCESS_PRIVATE))
+ throw Implementation (e);
+ }
+ }
+}
+
diff --git a/libcult/cult/sched/spin.hxx b/libcult/cult/sched/spin.hxx
new file mode 100644
index 0000000..c32e836
--- /dev/null
+++ b/libcult/cult/sched/spin.hxx
@@ -0,0 +1,41 @@
+// file : cult/sched/spin.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_SCHED_SPIN_HXX
+#define CULT_SCHED_SPIN_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <pthread.h>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ class Spin: public NonCopyable
+ {
+ public:
+ ~Spin ();
+
+ Spin ();
+
+ Void
+ lock ();
+
+ Boolean
+ try_lock ();
+
+ Void
+ unlock ();
+
+ private:
+ pthread_spinlock_t spin_;
+ };
+ }
+}
+
+#include <cult/sched/spin.ixx>
+
+#endif // CULT_SCHED_SPIN_HXX
diff --git a/libcult/cult/sched/spin.ixx b/libcult/cult/sched/spin.ixx
new file mode 100644
index 0000000..2accdde
--- /dev/null
+++ b/libcult/cult/sched/spin.ixx
@@ -0,0 +1,43 @@
+// file : cult/sched/spin.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/sched/exception.hxx>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ inline
+ Void Spin::
+ lock ()
+ {
+ if (Int e = pthread_spin_lock (&spin_))
+ throw Implementation (e);
+ }
+
+ inline
+ Boolean Spin::
+ try_lock ()
+ {
+ Int e (pthread_spin_trylock (&spin_));
+
+ switch (e)
+ {
+ case 0: return true;
+ case EBUSY: return false;
+ default: throw Implementation (e);
+ }
+ }
+
+ inline
+ Void Spin::
+ unlock ()
+ {
+ if (Int e = pthread_spin_unlock (&spin_))
+ throw Implementation (e);
+ }
+ }
+}
+
diff --git a/libcult/cult/sched/thread.cxx b/libcult/cult/sched/thread.cxx
new file mode 100644
index 0000000..89368b6
--- /dev/null
+++ b/libcult/cult/sched/thread.cxx
@@ -0,0 +1,211 @@
+// file : cult/sched/thread.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/sched/thread.hxx>
+#include <cult/sched/lock.hxx>
+#include <cult/sched/exception.hxx>
+
+#include <cult/mm/counter.hxx> // MM::inc_ref
+
+#include <cult/trace/stream.hxx>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ namespace
+ {
+ Trace::Stream tout ("Cult::Sched::Thread", 7);
+ }
+
+ namespace Bits
+ {
+ typedef Void* (*Routine) (Void*);
+
+ struct StartData
+ {
+ StartData (Shptr<Thread> const& thread, Routine routine, void* arg)
+ : thread_ (thread), routine_ (routine), arg_ (arg)
+ {
+ }
+
+ ~StartData ()
+ {
+ tout << 8 << "start data is being destroyed.";
+ }
+
+ Shptr<Thread> thread_;
+ Routine routine_;
+ Void* arg_;
+ };
+
+ static pthread_key_t key;
+ static pthread_once_t key_once = PTHREAD_ONCE_INIT;
+
+ extern "C" Void
+ cult_thread_dtor (Void* p)
+ {
+ // Exception in this function will result in the call
+ // to std::terminate().
+ //
+
+ tout << "cult_thread_dtor is being executed.";
+
+ Shptr<Thread> self (reinterpret_cast<Thread*> (p));
+ }
+
+ extern "C" Void
+ cult_thread_make_key ()
+ {
+ if (Int e = pthread_key_create (&key, &cult_thread_dtor))
+ throw Implementation (e);
+ }
+
+ extern "C" Void*
+ cult_thread_trampoline (Void* arg)
+ {
+ // Any failure in this function will result in the call
+ // to std::terminate().
+ //
+
+ Routine routine;
+
+ {
+ Shptr<StartData> data (reinterpret_cast<StartData*> (arg));
+
+ Thread* p (data->thread_.get ());
+
+ if (Int e = pthread_setspecific (key, p))
+ throw Implementation (e);
+ else
+ MM::inc_ref (p);
+
+ routine = data->routine_;
+ arg = data->arg_;
+ }
+
+ return routine (arg);
+ }
+ }
+
+ Thread::
+ Thread (Void* (*routine) (Void*), Void* arg)
+ : detached_ (false)
+ {
+ using Bits::StartData;
+
+ tout << "thread is being constructed.";
+
+ pthread_once (&Bits::key_once, &Bits::cult_thread_make_key);
+
+ Shptr<Thread> self (MM::inc_ref (this));
+
+ Shptr<StartData> data (new StartData (self, routine, arg));
+
+ if (Int e = pthread_create (&id_,
+ 0,
+ &Bits::cult_thread_trampoline,
+ data.get ()))
+ {
+ throw Implementation (e);
+ }
+ else
+ {
+ // If pthread_create did not fail then thread_trampoline
+ // will release the data.
+ //
+ data.release ();
+ }
+ }
+
+ Thread::
+ Thread ()
+ : id_ (pthread_self ()), detached_ (false) //@@ We can't be sure
+ // the it is detached.
+ {
+ tout << "thread is being adopted.";
+
+ pthread_once (&Bits::key_once, &Bits::cult_thread_make_key);
+
+ if (pthread_getspecific (Bits::key) != 0)
+ throw Adopted ();
+
+ Shptr<Thread> self (MM::inc_ref (this));
+
+ if(Int e = pthread_setspecific (Bits::key, this))
+ {
+ throw Implementation (e);
+ }
+ else
+ {
+ // TSD slot has the reference now.
+ //
+ self.release ();
+ }
+ }
+
+ Void* Thread::
+ join ()
+ {
+ Lock lock (mutex_);
+
+ if (detached_)
+ throw Joined ();
+
+ Void* r;
+
+ if (Int e = pthread_join (id_, &r))
+ throw Implementation (e);
+
+ detached_ = true;
+
+ return r;
+ }
+
+ Void Thread::
+ cancel ()
+ {
+ if (Int e = pthread_cancel (id_))
+ throw Implementation (e);
+ }
+
+ Void Thread::
+ exit (Void* ret)
+ {
+ pthread_exit (ret);
+ }
+
+ Shptr<Thread> Thread::
+ self ()
+ {
+ Thread* p (reinterpret_cast<Thread*> (pthread_getspecific (Bits::key)));
+
+ if (p != 0)
+ return Shptr<Thread> (MM::inc_ref (p));
+ else
+ throw Foreign ();
+ }
+
+ Void Thread::
+ test_cancel ()
+ {
+ pthread_testcancel ();
+ }
+
+ Thread::
+ ~Thread ()
+ {
+ tout << "thread is being destroyed.";
+
+ Lock lock (mutex_);
+
+ if (!detached_)
+ {
+ if (Int e = pthread_detach (id_))
+ throw Implementation (e);
+ }
+ }
+ }
+}
diff --git a/libcult/cult/sched/thread.hxx b/libcult/cult/sched/thread.hxx
new file mode 100644
index 0000000..49d6225
--- /dev/null
+++ b/libcult/cult/sched/thread.hxx
@@ -0,0 +1,86 @@
+// file : cult/sched/thread.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_SCHED_THREAD_HXX
+#define CULT_SCHED_THREAD_HXX
+
+#include <cult/types/fundamental.hxx>
+#include <cult/types/shptr.hxx>
+
+#include <cult/sched/mutex.hxx>
+#include <cult/sched/exception.hxx>
+
+#include <cult/mm/new.hxx>
+
+#include <pthread.h>
+
+namespace Cult
+{
+ namespace Sched
+ {
+ // Instantiating an automatic variable of type Thread results
+ // in undefined behavior (read core dump).
+ //
+ class Thread: public MM::ServiceAwareObject
+ {
+ public:
+ struct Exception: virtual Sched::Exception {};
+
+ public:
+ virtual
+ ~Thread ();
+
+ Thread (Void* (*StartRoutine) (Void*), Void* arg = 0);
+
+ // Adopt an existing thread. Adoption of a detached thread
+ // results in undefined behavior. Adoption of an already
+ // adopted thread results in Adopted exception.
+ //
+
+ struct Adopted: virtual Exception {};
+
+ Thread ();
+
+ public:
+ // Joining an already joined thread results in Joined exception.
+ //
+
+ struct Joined: virtual Exception {};
+
+ //@@ Need to work out the cancelled case.
+ //
+ Void*
+ join ();
+
+ Void
+ cancel ();
+
+ public:
+ static Void
+ exit (Void* ret);
+
+ // self() may not be called in TSD destructors. Call to self() from
+ // a foreign thread (i.e., one that is neither native nor adopted)
+ // results in Foreign exception.
+ //
+
+ struct Foreign: virtual Exception {};
+
+ static Shptr<Thread>
+ self ();
+
+ static Void
+ test_cancel ();
+
+ private:
+ pthread_t id_;
+
+ Boolean detached_;
+ Mutex mutex_;
+ };
+ }
+}
+
+#endif // CULT_SCHED_THREAD_HXX
diff --git a/libcult/cult/trace/log.cxx b/libcult/cult/trace/log.cxx
new file mode 100644
index 0000000..f77c2c3
--- /dev/null
+++ b/libcult/cult/trace/log.cxx
@@ -0,0 +1,49 @@
+// file : cult/trace/log.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/trace/log.hxx>
+
+#include <iostream>
+
+namespace Cult
+{
+ namespace Trace
+ {
+ Log::
+ Log (Int level)
+ : level_ (level)
+ {
+ }
+
+ Int Log::
+ level () const
+ {
+ return level_;
+ }
+
+ Void Log::
+ level (Int level)
+ {
+ level_ = level;
+ }
+
+ Log& Log::
+ instance ()
+ {
+ //@@ Need to use -once initialization. Plus is it legal to
+ // use trace in (static) dtors?
+ //
+ static Log log;
+ return log;
+ }
+
+ Void Log::
+ log_impl (Record const& r)
+ {
+ std::cerr << '[' << r.id () << ':' << r.level () << "] " << r.text ()
+ << std::endl;
+ }
+ }
+}
diff --git a/libcult/cult/trace/log.hxx b/libcult/cult/trace/log.hxx
new file mode 100644
index 0000000..2b21acf
--- /dev/null
+++ b/libcult/cult/trace/log.hxx
@@ -0,0 +1,51 @@
+// file : cult/trace/log.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_TRACE_LOG_HXX
+#define CULT_TRACE_LOG_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/trace/record.hxx>
+
+namespace Cult
+{
+ namespace Trace
+ {
+ class Log: public NonCopyable
+ {
+ public:
+ Log (Int level = -1);
+
+ public:
+ Int
+ level () const;
+
+ Void
+ level (Int level);
+
+ public:
+ //@@ should it be virtual?
+ //
+ Log&
+ operator<< (Record const& r);
+
+ public:
+ static Log&
+ instance ();
+
+ private:
+ Void
+ log_impl (Record const& r);
+
+ private:
+ Int level_;
+ };
+ }
+}
+
+#include <cult/trace/log.ixx>
+
+#endif // CULT_TRACE_LOG_HXX
diff --git a/libcult/cult/trace/log.ixx b/libcult/cult/trace/log.ixx
new file mode 100644
index 0000000..fbc23d9
--- /dev/null
+++ b/libcult/cult/trace/log.ixx
@@ -0,0 +1,20 @@
+// file : cult/trace/log.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Trace
+ {
+ inline
+ Log& Log::
+ operator<< (Record const& r)
+ {
+ if (r.level () <= level_)
+ log_impl (r);
+
+ return *this;
+ }
+ }
+}
diff --git a/libcult/cult/trace/null/record.ixx b/libcult/cult/trace/null/record.ixx
new file mode 100644
index 0000000..c93b1a0
--- /dev/null
+++ b/libcult/cult/trace/null/record.ixx
@@ -0,0 +1,45 @@
+// file : cult/trace/null/record.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Trace
+ {
+ inline
+ Record::
+ Record (Char const* id, Int level)
+ : id_ (id), level_ (level)
+ {
+ }
+
+ inline
+ Char const* Record::
+ text () const
+ {
+ return "";
+ }
+
+ inline
+ Char const* Record::
+ id () const
+ {
+ return id_;
+ }
+
+ inline
+ Int Record::
+ level () const
+ {
+ return level_;
+ }
+
+ inline
+ Void Record::
+ level (Int level)
+ {
+ level_ = level;
+ }
+ }
+}
diff --git a/libcult/cult/trace/null/record.txx b/libcult/cult/trace/null/record.txx
new file mode 100644
index 0000000..1413f1e
--- /dev/null
+++ b/libcult/cult/trace/null/record.txx
@@ -0,0 +1,18 @@
+// file : cult/trace/null/record.txx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Trace
+ {
+ template <typename T>
+ inline
+ Record& Record::
+ operator<< (T const&)
+ {
+ return *this;
+ }
+ }
+}
diff --git a/libcult/cult/trace/null/stream.ixx b/libcult/cult/trace/null/stream.ixx
new file mode 100644
index 0000000..45b6e78
--- /dev/null
+++ b/libcult/cult/trace/null/stream.ixx
@@ -0,0 +1,67 @@
+// file : cult/trace/null/stream.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Trace
+ {
+ inline
+ Stream::
+ Stream (Char const* id, Int level, Log& l)
+ : id_ (id), level_ (level), log_ (l)
+ {
+ }
+
+ inline
+ Char const* Stream::
+ id () const
+ {
+ return id_;
+ }
+
+ inline
+ Int Stream::
+ level () const
+ {
+ return level_;
+ }
+
+ inline
+ Stream& Stream::
+ operator << (Record const& r)
+ {
+ return *this;
+ }
+
+ inline
+ Stream::Mediator::
+ Mediator (Stream& s)
+ : s_ (s), r_ (s.id (), s.level ())
+ {
+ }
+
+ inline
+ Stream::Mediator::
+ ~Mediator ()
+ {
+ }
+
+ inline
+ Record&
+ operator<< (Stream::Mediator const& mc, Int level)
+ {
+ Stream::Mediator& m (const_cast<Stream::Mediator&> (mc));
+ // m.r_.level (level);
+ return m.r_;
+ }
+
+ inline
+ Record&
+ operator<< (Stream::Mediator const& mc, Char const* s)
+ {
+ return const_cast<Stream::Mediator&> (mc).r_;
+ }
+ }
+}
diff --git a/libcult/cult/trace/null/stream.txx b/libcult/cult/trace/null/stream.txx
new file mode 100644
index 0000000..e9ab70c
--- /dev/null
+++ b/libcult/cult/trace/null/stream.txx
@@ -0,0 +1,18 @@
+// file : cult/trace/null/stream.txx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Trace
+ {
+ template <typename T>
+ inline
+ Record&
+ operator<< (Stream::Mediator const& mc, T const&)
+ {
+ return const_cast<stream::mediator&> (mc).r_;
+ }
+ }
+}
diff --git a/libcult/cult/trace/record.hxx b/libcult/cult/trace/record.hxx
new file mode 100644
index 0000000..90276dd
--- /dev/null
+++ b/libcult/cult/trace/record.hxx
@@ -0,0 +1,86 @@
+// file : cult/trace/record.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_TRACE_RECORD_HXX
+#define CULT_TRACE_RECORD_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cstring> // memset
+#include <ostream>
+#include <streambuf>
+
+namespace Cult
+{
+ namespace Trace
+ {
+ class Record: public NonCopyable
+ {
+ public:
+ Record (Char const* id, Int level);
+
+ public:
+ Char const*
+ text () const;
+
+ Char const*
+ id () const;
+
+ Int
+ level () const;
+
+ Void
+ level (Int);
+
+ public:
+ template <typename T>
+ Record&
+ operator<< (T const& arg);
+
+ private:
+ Char const* id_;
+ Int level_;
+
+ //@@ need to wrap streambuf.
+ //
+ class FixedBuffer : public std::streambuf
+ {
+ public:
+ FixedBuffer (Char* buf, Size size)
+ {
+ std::memset (buf, 0, size);
+ setp (buf, buf + size - 1);
+ };
+
+ virtual int_type
+ overflow (int_type c)
+ {
+ return c;
+ }
+ };
+
+#ifndef CULT_TRACE_NULL
+ char buf_[1024];
+ FixedBuffer sbuf_;
+ std::ostream os_;
+#endif
+ };
+ }
+}
+
+#ifndef CULT_TRACE_NULL
+
+#include <cult/trace/record.ixx>
+#include <cult/trace/record.txx>
+
+#else
+
+#include <cult/trace/null/record.ixx>
+#include <cult/trace/null/record.txx>
+
+#endif
+
+
+#endif // CULT_TRACE_RECORD_HXX
diff --git a/libcult/cult/trace/record.ixx b/libcult/cult/trace/record.ixx
new file mode 100644
index 0000000..ae564a4
--- /dev/null
+++ b/libcult/cult/trace/record.ixx
@@ -0,0 +1,45 @@
+// file : cult/trace/record.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Trace
+ {
+ inline
+ Record::
+ Record (Char const* id, Int level)
+ : id_ (id), level_ (level), sbuf_ (buf_, sizeof (buf_)), os_ (&sbuf_)
+ {
+ }
+
+ inline
+ Char const* Record::
+ text () const
+ {
+ return buf_;
+ }
+
+ inline
+ Char const* Record::
+ id () const
+ {
+ return id_;
+ }
+
+ inline
+ Int Record::
+ level () const
+ {
+ return level_;
+ }
+
+ inline
+ Void Record::
+ level (Int level)
+ {
+ level_ = level;
+ }
+ }
+}
diff --git a/libcult/cult/trace/record.txx b/libcult/cult/trace/record.txx
new file mode 100644
index 0000000..0c4ef1b
--- /dev/null
+++ b/libcult/cult/trace/record.txx
@@ -0,0 +1,19 @@
+// file : cult/trace/record.txx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Trace
+ {
+ template <typename T>
+ inline
+ Record& Record::
+ operator<< (T const& arg)
+ {
+ os_ << arg;
+ return *this;
+ }
+ }
+}
diff --git a/libcult/cult/trace/stream.hxx b/libcult/cult/trace/stream.hxx
new file mode 100644
index 0000000..728e973
--- /dev/null
+++ b/libcult/cult/trace/stream.hxx
@@ -0,0 +1,74 @@
+// file : cult/trace/stream.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_TRACE_STREAM_HXX
+#define CULT_TRACE_STREAM_HXX
+
+#include <cult/types/fundamental.hxx>
+
+#include <cult/trace/log.hxx>
+#include <cult/trace/record.hxx>
+
+namespace Cult
+{
+ namespace Trace
+ {
+ class Stream: public NonCopyable
+ {
+ public:
+ Stream (Char const* id, Int level, Log& l = Log::instance ());
+
+ public:
+ Char const*
+ id () const;
+
+ Int
+ level () const;
+
+ public:
+ Stream&
+ operator<< (Record const& r);
+
+ private:
+ struct Mediator
+ {
+ ~Mediator ();
+ Mediator (Stream&);
+
+ Stream& s_;
+ Record r_;
+ };
+
+ friend Record&
+ operator<< (Mediator const&, Int level);
+
+ friend Record&
+ operator<< (Mediator const&, Char const* s);
+
+ template <typename T>
+ friend Record&
+ operator<< (Mediator const&, T const& arg);
+
+ private:
+ Char const* id_;
+ Int level_;
+ Log& log_;
+ };
+ }
+}
+
+#ifndef CULT_TRACE_NULL
+
+#include <cult/trace/stream.ixx>
+#include <cult/trace/stream.txx>
+
+#else
+
+#include <cult/trace/null/stream.ixx>
+#include <cult/trace/null/stream.txx>
+
+#endif
+
+#endif // CULT_TRACE_STREAM_HXX
diff --git a/libcult/cult/trace/stream.ixx b/libcult/cult/trace/stream.ixx
new file mode 100644
index 0000000..718383c
--- /dev/null
+++ b/libcult/cult/trace/stream.ixx
@@ -0,0 +1,76 @@
+// file : cult/trace/stream.ixx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Trace
+ {
+ // Stream::Mediator
+ //
+ inline
+ Stream::Mediator::
+ Mediator (Stream& s)
+ : s_ (s), r_ (s.id (), s.level ())
+ {
+ }
+
+ inline
+ Stream::Mediator::
+ ~Mediator ()
+ {
+ s_ << r_;
+ }
+
+ // Stream
+ //
+ inline
+ Stream::
+ Stream (Char const* id, Int level, Log& log)
+ : id_ (id), level_ (level), log_ (log)
+ {
+ }
+
+ inline
+ char const* Stream::
+ id () const
+ {
+ return id_;
+ }
+
+ inline
+ int Stream::
+ level () const
+ {
+ return level_;
+ }
+
+ //
+ //
+ inline
+ Stream& Stream::
+ operator << (Record const& r)
+ {
+ log_ << r;
+ return *this;
+ }
+
+ inline
+ Record&
+ operator<< (Stream::Mediator const& mc, Int level)
+ {
+ Stream::Mediator& m (const_cast<Stream::Mediator&> (mc));
+ m.r_.level (level);
+ return m.r_;
+ }
+
+ inline
+ Record&
+ operator<< (Stream::Mediator const& mc, Char const* s)
+ {
+ Stream::Mediator& m (const_cast<Stream::Mediator&> (mc));
+ return m.r_ << s;
+ }
+ }
+}
diff --git a/libcult/cult/trace/stream.txx b/libcult/cult/trace/stream.txx
new file mode 100644
index 0000000..1ac20ed
--- /dev/null
+++ b/libcult/cult/trace/stream.txx
@@ -0,0 +1,19 @@
+// file : cult/trace/stream.txx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+namespace Cult
+{
+ namespace Trace
+ {
+ template <typename T>
+ inline
+ Record&
+ operator<< (Stream::Mediator const& mc, T const& arg)
+ {
+ Stream::Mediator& m (const_cast<Stream::Mediator&> (mc));
+ return m.r_ << arg;
+ }
+ }
+}
diff --git a/libcult/cult/types.hxx b/libcult/cult/types.hxx
new file mode 100644
index 0000000..5e4c9c2
--- /dev/null
+++ b/libcult/cult/types.hxx
@@ -0,0 +1,14 @@
+// file : cult/types.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_TYPES_HXX
+#define CULT_TYPES_HXX
+
+#include <cult/types/fundamental.hxx>
+#include <cult/types/string.hxx>
+#include <cult/types/evptr.hxx>
+#include <cult/types/shptr.hxx>
+
+#endif // CULT_TYPES_HXX
diff --git a/libcult/cult/types/evptr.hxx b/libcult/cult/types/evptr.hxx
new file mode 100644
index 0000000..a39cd86
--- /dev/null
+++ b/libcult/cult/types/evptr.hxx
@@ -0,0 +1,21 @@
+// file : cult/types/evptr.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_TYPES_EVPTR_HXX
+#define CULT_TYPES_EVPTR_HXX
+
+#include <cult/mm/evptr.hxx>
+
+namespace Cult
+{
+ namespace Types
+ {
+ using MM::Evptr;
+ }
+
+ using Types::Evptr;
+}
+
+#endif // CULT_TYPES_EVPTR_HXX
diff --git a/libcult/cult/types/fundamental.hxx b/libcult/cult/types/fundamental.hxx
new file mode 100644
index 0000000..01116f1
--- /dev/null
+++ b/libcult/cult/types/fundamental.hxx
@@ -0,0 +1,175 @@
+// file : cult/types/fundamental.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_TYPES_FUNDAMENTAL_HXX
+#define CULT_TYPES_FUNDAMENTAL_HXX
+
+#include <cstddef> // std::size_t, std::ptrdiff_t
+
+namespace Cult
+{
+ namespace Types
+ {
+ namespace Fundamental
+ {
+ // Fundamental types
+ //
+ typedef void Void;
+
+ typedef bool Boolean;
+
+ typedef char Char;
+ typedef wchar_t WideChar;
+
+ typedef short Short;
+ typedef unsigned short UnsignedShort;
+
+ typedef int Int;
+ typedef unsigned int UnsignedInt;
+
+ typedef long Long;
+ typedef unsigned long UnsignedLong;
+
+ //@@ what would be a good name for float, double and long double?
+ // ShortFloat, Float and LongFloat
+ // ShortReal, Real, LongReal
+
+ typedef std::size_t Size;
+ typedef std::ptrdiff_t PtrDifference;
+ typedef Size Index;
+
+ // Fixed-size types.
+ //
+ typedef signed char Int8;
+ typedef unsigned char UnsignedInt8;
+
+ typedef signed short Int16;
+ typedef unsigned short UnsignedInt16;
+
+ typedef signed int Int32;
+ typedef unsigned int UnsignedInt32;
+
+ typedef signed long long Int64;
+ typedef unsigned long long UnsignedInt64;
+
+
+ typedef float Float32;
+ typedef double Float64;
+ typedef long double Float128; // Only 96 on x86-32.
+ }
+
+
+ // Fundamental types
+ //
+ using Fundamental::Void;
+
+ using Fundamental::Boolean;
+
+ using Fundamental::Char;
+ using Fundamental::WideChar;
+
+ using Fundamental::Short;
+ using Fundamental::UnsignedShort;
+
+ using Fundamental::Int;
+ using Fundamental::UnsignedInt;
+
+ using Fundamental::Long;
+ using Fundamental::UnsignedLong;
+
+ using Fundamental::Size;
+ using Fundamental::PtrDifference;
+ using Fundamental::Index;
+
+
+ // Fixed-size types.
+ //
+ using Fundamental::Int8;
+ using Fundamental::UnsignedInt8;
+
+ using Fundamental::Int16;
+ using Fundamental::UnsignedInt16;
+
+ using Fundamental::Int32;
+ using Fundamental::UnsignedInt32;
+
+ using Fundamental::Int64;
+ using Fundamental::UnsignedInt64;
+
+
+ using Fundamental::Float32;
+ using Fundamental::Float64;
+ using Fundamental::Float128; // Only 96 on x86-32.
+
+
+ // Note: make sure you inherit publicly from this type for
+ // it could be used for metaprogramming.
+ //
+ class NonCopyable
+ {
+ NonCopyable (NonCopyable const&);
+
+ NonCopyable&
+ operator= (NonCopyable const&);
+
+ protected:
+ NonCopyable ()
+ {
+ }
+ };
+
+ // class Clonable ?
+ //
+
+ }
+
+ // Fundamental types
+ //
+ using Types::Void;
+
+ using Types::Boolean;
+
+ using Types::Char;
+ using Types::WideChar;
+
+ using Types::Short;
+ using Types::UnsignedShort;
+
+ using Types::Int;
+ using Types::UnsignedInt;
+
+ using Types::Long;
+ using Types::UnsignedLong;
+
+ using Types::Size;
+ using Types::PtrDifference;
+ using Types::Index;
+
+
+ // Fixed-size types.
+ //
+ using Types::Int8;
+ using Types::UnsignedInt8;
+
+ using Types::Int16;
+ using Types::UnsignedInt16;
+
+ using Types::Int32;
+ using Types::UnsignedInt32;
+
+ using Types::Int64;
+ using Types::UnsignedInt64;
+
+
+ using Types::Float32;
+ using Types::Float64;
+ using Types::Float128; // Only 96 on x86-32.
+
+ //
+ //
+ using Types::NonCopyable;
+}
+
+#endif // CULT_TYPES_FUNDAMENTAL_HXX
diff --git a/libcult/cult/types/shptr.hxx b/libcult/cult/types/shptr.hxx
new file mode 100644
index 0000000..c5d2d66
--- /dev/null
+++ b/libcult/cult/types/shptr.hxx
@@ -0,0 +1,21 @@
+// file : cult/types/shptr.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_TYPES_SHPTR_HXX
+#define CULT_TYPES_SHPTR_HXX
+
+#include <cult/mm/shptr.hxx>
+
+namespace Cult
+{
+ namespace Types
+ {
+ using MM::Shptr;
+ }
+
+ using Types::Shptr;
+}
+
+#endif // CULT_TYPES_SHPTR_HXX
diff --git a/libcult/cult/types/string.hxx b/libcult/cult/types/string.hxx
new file mode 100644
index 0000000..108f830
--- /dev/null
+++ b/libcult/cult/types/string.hxx
@@ -0,0 +1,397 @@
+// file : cult/types/string.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_TYPES_STRING_HXX
+#define CULT_TYPES_STRING_HXX
+
+#include <cult/types/fundamental.hxx>
+#include <cult/eh/exception.hxx>
+
+//@@ Dependency on 'containers'. Maybe move iterator to 'types'?
+//
+#include <cult/containers/iterator.hxx>
+
+#include <string>
+#include <cstdlib> // mbstowcs
+
+namespace Cult
+{
+ namespace Types
+ {
+ //@@ Maybe create StringFwd.hxx
+ //
+
+ namespace Bits
+ {
+ struct None {};
+
+ template <typename C>
+ struct NarrowerChar
+ {
+ typedef None Type;
+ };
+
+
+ template <>
+ struct NarrowerChar<WideChar>
+ {
+ typedef Char Type;
+ };
+ }
+
+ template <typename C,
+ typename NarrowerChar = typename Bits::NarrowerChar<C>::Type>
+ class StringTemplate;
+
+ template <>
+ class StringTemplate<Bits::None, Bits::None>
+ {
+ };
+
+
+ template <typename C, typename NarrowerChar>
+ class StringTemplate : public std::basic_string<C>
+ {
+ typedef std::basic_string<C> Base;
+ typedef std::basic_string<NarrowerChar> NarrowerBase;
+
+ Base&
+ base ()
+ {
+ return *this;
+ }
+
+ Base const&
+ base () const
+ {
+ return *this;
+ }
+
+ public:
+ typedef typename Base::value_type Value;
+
+ /*
+ typedef traits traits_type;
+ typedef typename traits::char_type value_type;
+ typedef Allocator allocator_type;
+ typedef typename Allocator::size_type size_type;
+ typedef typename Allocator::difference_type difference_type;
+ typedef typename Allocator::reference reference;
+ typedef typename Allocator::const_reference const_reference;
+ typedef typename Allocator::pointer pointer;
+ typedef typename Allocator::const_pointer const_pointer;
+ */
+
+ typedef
+ Containers::IteratorAdapter<typename Base::iterator>
+ Iterator;
+
+ typedef
+ Containers::IteratorAdapter<typename Base::const_iterator>
+ ConstIterator;
+
+
+ typedef
+ Containers::IteratorAdapter<typename Base::reverse_iterator>
+ ReverseIterator;
+
+ typedef
+ Containers::IteratorAdapter<typename Base::const_reverse_iterator>
+ ConstReverseIterator;
+
+
+ using Base::npos;
+ using Base::empty;
+
+ public:
+ explicit
+ StringTemplate ()
+ {
+ }
+
+ StringTemplate (StringTemplate const& str, Size pos, Size n = npos)
+ : Base (str, pos, n)
+ {
+ }
+
+ StringTemplate (Value const* s, Size n)
+ : Base (s, n)
+ {
+ }
+
+ StringTemplate (Value const* s)
+ : Base (s)
+ {
+ }
+
+ StringTemplate (Size n, Value c)
+ : Base (n, c)
+ {
+ }
+
+ template <typename InputIterator>
+ StringTemplate(InputIterator begin, InputIterator end)
+ : Base (begin, end)
+ {
+ }
+
+ StringTemplate (StringTemplate const& other)
+ : Base (other)
+ {
+ }
+
+ // Conversion from Base.
+ //
+ StringTemplate (Base const& str)
+ : Base (str)
+ {
+ }
+
+ // Conversion from the Narrower type. Experimental.
+ //
+ StringTemplate (NarrowerChar const* s)
+ {
+ from_narrow (s);
+ }
+
+ StringTemplate (StringTemplate<NarrowerChar> const& other)
+ {
+ from_narrow (other.c_str ());
+ }
+
+ StringTemplate (NarrowerBase const& other)
+ {
+ from_narrow (other.c_str ());
+ }
+
+ // Conversion to the Narrower type. Experimental.
+ //
+ struct NonRepresentable: virtual EH::Exception {};
+
+ StringTemplate<NarrowerChar>
+ to_narrow () const;
+
+ // Assignment.
+ //
+ StringTemplate&
+ operator= (StringTemplate const& str)
+ {
+ base () = str;
+ return *this;
+ }
+
+ StringTemplate&
+ operator= (Value const* s)
+ {
+ base () = s;
+ return *this;
+ }
+
+ StringTemplate&
+ operator= (Value c)
+ {
+ base () = c;
+ return *this;
+ }
+
+ // Assignment from Base.
+ //
+ StringTemplate&
+ operator= (Base const& str)
+ {
+ base () = str;
+ return *this;
+ }
+
+ public:
+ StringTemplate&
+ operator+= (StringTemplate const& str)
+ {
+ base () += str;
+ return *this;
+ }
+
+ StringTemplate&
+ operator+= (Value const* s)
+ {
+ base () += s;
+ return *this;
+ }
+
+ StringTemplate&
+ operator+= (Value c)
+ {
+ base () += c;
+ return *this;
+ }
+
+
+ public:
+ Iterator
+ begin ()
+ {
+ return Iterator (base ().begin ());
+ }
+
+ Iterator
+ end ()
+ {
+ return Iterator (base ().end ());
+ }
+
+
+ ConstIterator
+ begin () const
+ {
+ return ConstIterator (base ().begin ());
+ }
+
+ ConstIterator
+ end () const
+ {
+ return ConstIterator (base ().end ());
+ }
+
+ //
+ //
+
+ ReverseIterator
+ rbegin ()
+ {
+ return ReverseIterator (base ().rbegin ());
+ }
+
+ ReverseIterator
+ rend ()
+ {
+ return ReverseIterator (base ().rend ());
+ }
+
+
+ ConstReverseIterator
+ rbegin () const
+ {
+ return ConstReverseIterator (base ().rbegin ());
+ }
+
+ ConstReverseIterator
+ rend () const
+ {
+ return ConstReverseIterator (base ().rend ());
+ }
+
+
+ // Conversion to Boolean.
+ //
+ private:
+ typedef Void (StringTemplate::*BooleanConvertable)();
+
+ void
+ true_ ()
+ {
+ }
+
+ public:
+ operator BooleanConvertable () const
+ {
+ return empty () ? 0 : &StringTemplate::true_;
+ }
+
+ private:
+ Void
+ from_narrow (NarrowerChar const* s);
+ };
+
+
+ template<typename C>
+ StringTemplate<C>
+ operator+ (StringTemplate<C> const& lhs, StringTemplate<C> const& rhs)
+ {
+ return StringTemplate<C> (lhs) += rhs;
+ }
+
+ template<typename C>
+ StringTemplate<C>
+ operator+ (C const* lhs, StringTemplate<C> const& rhs)
+ {
+ return StringTemplate<C> (lhs) += rhs;
+ }
+
+ template<typename C>
+ StringTemplate<C>
+ operator+ (StringTemplate<C> const& lhs, C const* rhs)
+ {
+ return StringTemplate<C> (lhs) += rhs;
+ }
+
+ template<typename C>
+ StringTemplate<C>
+ operator+ (C lhs, StringTemplate<C> const& rhs)
+ {
+ return StringTemplate<C> (1, lhs) += rhs;
+ }
+
+
+ template<typename C>
+ StringTemplate<C>
+ operator+ (StringTemplate<C> const& lhs, C rhs)
+ {
+ return StringTemplate<C> (lhs) += rhs;
+ }
+
+ //
+ //
+ typedef StringTemplate<Char> String;
+ typedef StringTemplate<Char> NarrowString;
+ typedef StringTemplate<WideChar> WideString;
+
+ // Specialization for Char to WideChar conversion.
+ //
+ template <>
+ inline Void StringTemplate<WideChar, Char>::
+ from_narrow (Char const* s)
+ {
+ Size size (std::mbstowcs (0, s, 0) + 1);
+
+ // I dare to change the guts!
+ //
+ resize (size - 1);
+
+ WideChar* p (const_cast<WideChar*> (data ()));
+
+ std::mbstowcs (p, s, size);
+ }
+
+ // Specialization for WideChar to Char conversion.
+ //
+ template <>
+ inline StringTemplate<Char> StringTemplate<WideChar, Char>::
+ to_narrow () const
+ {
+ Size size (std::wcstombs (0, c_str (), 0));
+
+ if (size == Size (-1))
+ throw NonRepresentable ();
+
+ // I dare to change the guts!
+ //
+ StringTemplate<Char> r;
+ r.resize (size);
+
+ Char* p (const_cast<Char*> (r.data ()));
+
+ std::wcstombs (p, c_str (), size + 1);
+
+ return r;
+ }
+ }
+
+ using Types::String;
+ using Types::NarrowString;
+ using Types::WideString;
+ using Types::StringTemplate;
+}
+
+#endif // CULT_TYPES_STRING_HXX
diff --git a/libcult/documentation/BUGS b/libcult/documentation/BUGS
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/libcult/documentation/BUGS
@@ -0,0 +1,2 @@
+
+
diff --git a/libcult/documentation/CORE b/libcult/documentation/CORE
new file mode 100644
index 0000000..76e1a69
--- /dev/null
+++ b/libcult/documentation/CORE
@@ -0,0 +1,14 @@
+* types
+
+* eh
+
+* trace
+
+* mm -> eh, sched
+
+* meta
+
+* rtti -> containers!!
+
+* sched -> eh, mm
+
diff --git a/libcult/documentation/DESIGN b/libcult/documentation/DESIGN
new file mode 100644
index 0000000..6d469a5
--- /dev/null
+++ b/libcult/documentation/DESIGN
@@ -0,0 +1,12 @@
+
+@@ First layer include language usage policies (e.g. namespaces, eh)
+ and base libraries:
+
+ eh, threading, memory management, tracing, containers
+
+@@ Tracing in libraries? Is it possible?
+
+
+
+
+ \ No newline at end of file
diff --git a/libcult/documentation/DOC b/libcult/documentation/DOC
new file mode 100644
index 0000000..a593886
--- /dev/null
+++ b/libcult/documentation/DOC
@@ -0,0 +1 @@
+@@ Update README, NEWS and INSTALL (from index.xhtml)
diff --git a/libcult/documentation/NOTES b/libcult/documentation/NOTES
new file mode 100644
index 0000000..81b48e5
--- /dev/null
+++ b/libcult/documentation/NOTES
@@ -0,0 +1,3 @@
+@@ SUS dlsym has some ideas about symbol interpositions.
+ This could be relevant to the problem of calling orginal
+ operator new.
diff --git a/libcult/documentation/RELEASE b/libcult/documentation/RELEASE
new file mode 100644
index 0000000..3a7f1ab
--- /dev/null
+++ b/libcult/documentation/RELEASE
@@ -0,0 +1 @@
+@@ copyright
diff --git a/libcult/documentation/THOGHTS b/libcult/documentation/THOGHTS
new file mode 100644
index 0000000..7bf1767
--- /dev/null
+++ b/libcult/documentation/THOGHTS
@@ -0,0 +1 @@
+@@ Access local resources the same way you access remote resources.
diff --git a/libcult/documentation/TODO b/libcult/documentation/TODO
new file mode 100644
index 0000000..a35515b
--- /dev/null
+++ b/libcult/documentation/TODO
@@ -0,0 +1,3 @@
+@@ installation
+
+@@ Add short description for each example. \ No newline at end of file
diff --git a/libcult/documentation/TODO-CLI b/libcult/documentation/TODO-CLI
new file mode 100644
index 0000000..242c0da
--- /dev/null
+++ b/libcult/documentation/TODO-CLI
@@ -0,0 +1,7 @@
+@@ I should not assume that Utility::CommandLine is the only mechanism
+ used to parse command line. Application developer may be using
+ different components that employ different command line parsers.
+ Thus it seem to me that I should use argv/argc as input/output
+ format.
+
+@@ Notion of a default command (e.g., a& --help).
diff --git a/libcult/documentation/TODO-EH b/libcult/documentation/TODO-EH
new file mode 100644
index 0000000..ed7c133
--- /dev/null
+++ b/libcult/documentation/TODO-EH
@@ -0,0 +1,5 @@
+@@ Since there is only one header in eh maybe I should just make it
+ top-level eh.hxx? One disadvantage of this is that I will have to
+ qualify it with cult::exception when I inherit class-specific
+ exception base (maybe it is not too bad actually).
+ \ No newline at end of file
diff --git a/libcult/documentation/TODO-META b/libcult/documentation/TODO-META
new file mode 100644
index 0000000..21eabd5
--- /dev/null
+++ b/libcult/documentation/TODO-META
@@ -0,0 +1,2 @@
+
+@@ Move meta tests from other places to meta/.
diff --git a/libcult/documentation/TODO-MM b/libcult/documentation/TODO-MM
new file mode 100644
index 0000000..7979d15
--- /dev/null
+++ b/libcult/documentation/TODO-MM
@@ -0,0 +1,3 @@
+@@ new with arbitrary alignment
+
+%% Does not work if thread is not the most derived type. See 12.7.5.
diff --git a/libcult/documentation/TODO-SCHED b/libcult/documentation/TODO-SCHED
new file mode 100644
index 0000000..eeea3bb
--- /dev/null
+++ b/libcult/documentation/TODO-SCHED
@@ -0,0 +1,12 @@
+@@ typedef std::thread_cancel in cult::os::sched?
+
+@@ maybe define USE_CXX_UNWIND or something in pthread.h
+ so I can detect that?
+
+@@ rename auto_lock to lock?
+
+@@ maybe add sched::exception: os::exception i.e., "scheduling exception"?
+
+@@ I am throwing exceptions in sched::thread that are not derived from
+ sched::exception.
+ \ No newline at end of file
diff --git a/libcult/documentation/cli/index.xhtml b/libcult/documentation/cli/index.xhtml
new file mode 100644
index 0000000..9c3f1a8
--- /dev/null
+++ b/libcult/documentation/cli/index.xhtml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/cli/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation/cli</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="libcult,c++,command,line,interface,option,argument"/>
+ <meta name="description" content="libcult/documentation/cli"/>
+
+ <link rel="stylesheet" type="text/css" href="../default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href="../.."><code>libcult</code></a> <code>/</code>
+<a href=".."><code>documentation</code></a> <code>/</code>
+<code>cli</code>
+</p>
+</div>
+
+<div id="content">
+<p>The <em>libcult</em> command line interace library provides
+mechanisms for extracting informtaion from the command line. The
+following code fragment is from <code>libcult/examples/cli</code>:</p>
+
+<pre class="cxx">
+namespace
+{
+ extern Char const help[] = "help";
+ extern Char const version[] = "version";
+ extern Char const outdir[] = "outdir";
+}
+
+typedef
+CLI::Options&lt;help, Boolean,
+ version, Boolean,
+ outdir, String&gt;
+Options;
+
+Int
+main (Int argc, Char* argv[])
+{
+ try
+ {
+ Options options (CLI::parse&lt;Options&gt; (argc, argv));
+
+ if (options.value&lt;help&gt; ())
+ {
+ cerr &lt;&lt; "usage: " &lt;&lt; argv[0] &lt;&lt; " [--help] [--version] [--outdir &lt;dir&gt;]"
+ &lt;&lt; endl;
+ return 0;
+ }
+
+ if (options.value&lt;version&gt; ())
+ {
+ cerr &lt;&lt; argv[0] &lt;&lt; " 1.2.3" &lt;&lt; endl;
+ return 0;
+ }
+
+ if (String dir = options.value&lt;outdir&gt; ())
+ {
+ cerr &lt;&lt; "outdir: " &lt;&lt; dir &lt;&lt; endl;
+ }
+ }
+ catch (CLI::UnexpectedOption const&amp; e)
+ {
+ cerr &lt;&lt; "unexpected option " &lt;&lt; e.option () &lt;&lt;endl;
+ }
+ catch (CLI::OptionFormat const&amp; e)
+ {
+ cerr &lt;&lt; "bad format for " &lt;&lt; e.option () &lt;&lt; endl;
+ }
+}
+</pre>
+</div>
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/documentation/default.css b/libcult/documentation/default.css
new file mode 100644
index 0000000..7242a94
--- /dev/null
+++ b/libcult/documentation/default.css
@@ -0,0 +1,160 @@
+body {
+ font-family : sans-serif;
+ font-weight : normal;
+
+ color : black;
+ background : white;
+
+ max-width : 42em;
+ padding : 2em 2em 2em 3em;
+ margin : 0 auto;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family : sans-serif;
+ font-weight : 500;
+}
+
+h1 { font-size : 170%; }
+h2 { font-size : 145%; }
+h3 { font-size : 125%; }
+h4 { font-size : 110%; }
+h5 { font-size : 106%; }
+h6 { font-size : 100%; }
+
+
+p.indent {
+ margin-left : 1.5em;
+}
+
+
+/* table of content */
+ul.toc li {
+ padding : .4em 0em 0em 0em;
+}
+
+
+
+/* list of links */
+ul.menu {
+ list-style-type : none;
+}
+
+ul.menu li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+}
+
+
+
+/* @@ I should probably use child selector here */
+/* list with multiline list-elements */
+ul.multiline li {
+ padding-top : 0.4em;
+ padding-bottom : 0.4em;
+}
+
+ol.multiline li {
+ padding-top : 0.4em;
+ padding-bottom : 0.4em;
+}
+
+dl.multiline dd {
+ padding-top : 0.4em;
+ padding-bottom : 0.4em;
+}
+
+/* code */
+
+code {
+ font-size : 114%;
+ font-family : monospace;
+}
+
+
+/* C++ code snippet */
+pre.cxx {
+
+ margin-top : 0em;
+ margin-bottom : 2em;
+
+ margin-left : 1em;
+}
+
+
+
+/* make code snippet */
+pre.make {
+
+ margin-top : 0em;
+ margin-bottom : 2em;
+
+ margin-left : 1em;
+}
+
+
+
+/* terminal output */
+pre.term {
+
+ margin-top : 0em;
+ margin-bottom : 2em;
+
+ margin-left : 1em;
+}
+
+
+/* Images */
+div.center {
+ text-align: center;
+}
+
+/* Navigation. */
+#navigation {
+ margin-top: 1em;
+ border-bottom: 1px dashed #000000;
+}
+
+#content {
+ margin-top: 2.5em;
+}
+
+
+/* Document info. */
+#docinfo {
+ margin-top: 4em;
+ border-top: 1px dashed #000000;
+ font-size: 70%;
+}
+
+/* distribution terms */
+div.terms {
+ font-size : 114%;
+ font-family : monospace;
+}
+
+
+
+/* Footnote */
+
+#footnote {
+ margin-top: 2em;
+}
+
+#footnote hr {
+ margin-left: 0;
+ margin-bottom: 1.5em;
+ width: 8em;
+ border-top: 1px solid #000000;
+ border-right: none;
+ border-bottom: none;
+ border-left: none;
+
+}
+
+#footnote p {
+ font-size: .91em;
+ text-indent: -0.8em;
+ padding-left: 0.8em;
+}
+
diff --git a/libcult/documentation/dr/index.xhtml b/libcult/documentation/dr/index.xhtml
new file mode 100644
index 0000000..0726adb
--- /dev/null
+++ b/libcult/documentation/dr/index.xhtml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/dr/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation/dr</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="libcult,c++,data,representation,xdr"/>
+ <meta name="description" content="libcult/documentation/dr"/>
+
+ <link rel="stylesheet" type="text/css" href="../default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href="../.."><code>libcult</code></a> <code>/</code>
+<a href=".."><code>documentation</code></a> <code>/</code>
+<code>dr</code>
+</p>
+</div>
+
+<div id="content">
+<p>The <em>libcult</em> data representation library provides serialization
+streams for reading/writing data representations. Only XDR is supported
+in current version.</p>
+</div>
+
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/documentation/eh/index.xhtml b/libcult/documentation/eh/index.xhtml
new file mode 100644
index 0000000..7847c11
--- /dev/null
+++ b/libcult/documentation/eh/index.xhtml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/eh/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation/eh</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="libcult,c++,exception,handling"/>
+ <meta name="description" content="libcult/documentation/eh"/>
+
+ <link rel="stylesheet" type="text/css" href="../default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href="../.."><code>libcult</code></a> <code>/</code>
+<a href=".."><code>documentation</code></a> <code>/</code>
+<code>eh</code>
+</p>
+</div>
+
+<div id="content">
+<p>The <code>libcult</code> exception handling library defines a base
+exception type to be used by the rest of <code>libcult</code>. It has
+a very basic interface:</p>
+
+<pre class="cxx">
+namespace Cult
+{
+ namespace EH
+ {
+ class Exception: public virtual std::exception
+ {
+ public:
+ virtual char const*
+ what () const throw ();
+ };
+ }
+}
+</pre>
+
+<p>It derives from <code>std::exception</code> to allow catching
+all exceptions with a single handler. Default implementation of the
+<code>what()</code> member function returns type-name of the exception.
+</p>
+
+<p>Every non-trivial library in <em>libcult</em> derives its own
+base exception which all library-defined exceptions inherit. This
+way you can catch all exceptions from a library with one handler.</p>
+
+<p>Sometimes it may seem convenient to further partition (by providing
+corresponding base classes) exceptions space into <em>logic</em>
+exceptions (shared by all implementations) and <em>implementation</em>
+exceptions. For example, if you pass an allocator illegal size 0 then
+the allocator throws an exception which can be classified as a logic
+exception. If, however, you passed valid size but there is not enough
+memory then the allocator throws an exception which can be classified
+as an implementation exception<sup><a href="#fn1">1</a></sup>.</p>
+
+<p>The problem with this approach lies in the fact that someone's logic
+exception is someone else's implementation exception. Consider, for
+instance, a buffer type that is implemented in terms of our allocator.
+If the buffer happened to request a memory block of size 0 and let
+the exception propagate through the interface boundaries it is no longer
+a logic exception.</p>
+
+
+<div id="footnote">
+<hr/>
+<p id="fn1"><sup>1</sup> It can be argued that the
+<code>NoMemory</code> exception should rather be classified
+as logic. However, let's assume there are allocator implementations
+that have infinite memory.</p>
+</div>
+
+</div>
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/documentation/index.xhtml b/libcult/documentation/index.xhtml
new file mode 100644
index 0000000..cc2f45d
--- /dev/null
+++ b/libcult/documentation/index.xhtml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="c++,library"/>
+ <meta name="description" content="libcult/documentation"/>
+
+ <link rel="stylesheet" type="text/css" href="default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href=".."><code>libcult</code></a> <code>/</code>
+<code>documentation</code>
+</p>
+</div>
+
+<div id="content">
+<p>A number of lower-level libraries are grouped to form a core. Certain
+organizational rules are relaxed for this group. For instance, libraries
+from the core are allowed to have cyclic dependecies and can inject names
+into the top-level namespace <code>cult</code>. Below is the list of
+libraries that currently constitute the core:</p>
+
+<ul class="menu">
+ <li><a href="eh/"><code>eh</code></a></li>
+ <li><a href="meta/"><code>meta</code></a></li>
+ <li><a href="mm/"><code>mm</code></a></li>
+ <li><a href="rtti/"><code>rtti</code></a></li>
+ <li><a href="sched/"><code>sched</code></a></li>
+ <li><a href="trace/"><code>trace</code></a></li>
+ <li><a href="types/"><code>types</code></a></li>
+</ul>
+
+<p>The rest of the libraries normally depend on the core but not
+vice-versa. Below is the list of them:</p>
+
+<ul class="menu">
+ <li><a href="cli/"><code>cli</code></a></li>
+ <!--li><a href="containers/"><code>containers</code></a></li -->
+ <li><a href="dr/"><code>dr</code></a></li>
+ <li><a href="os/"><code>os</code></a></li>
+</ul>
+</div>
+
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/documentation/meta/index.xhtml b/libcult/documentation/meta/index.xhtml
new file mode 100644
index 0000000..15ae7a5
--- /dev/null
+++ b/libcult/documentation/meta/index.xhtml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/meta/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation/meta</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="libcult,c++,meta,programming"/>
+ <meta name="description" content="libcult/documentation/meta"/>
+
+ <link rel="stylesheet" type="text/css" href="../default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href="../.."><code>libcult</code></a> <code>/</code>
+<a href=".."><code>documentation</code></a> <code>/</code>
+<code>meta</code>
+</p>
+</div>
+
+<div id="content">
+<p>The <em>libcult</em> metaprogramming library provides a template
+metaprogramming framework, tests and transformations.</p>
+
+<p>Tests:</p>
+
+<ul class="menu">
+ <li><code>class_p</code></li>
+ <li><code>polymorphic_p</code></li>
+</ul>
+
+<p>Transformations:</p>
+
+<ul class="menu">
+ <li><code>remove_c</code></li>
+ <li><code>remove_v</code></li>
+ <li><code>remove_cv</code></li>
+</ul>
+</div>
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/documentation/mm/index.xhtml b/libcult/documentation/mm/index.xhtml
new file mode 100644
index 0000000..8ed79d4
--- /dev/null
+++ b/libcult/documentation/mm/index.xhtml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/mm/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation/mm</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="libcult,c++,memory,management"/>
+ <meta name="description" content="libcult/documentation/mm"/>
+
+ <link rel="stylesheet" type="text/css" href="../default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href="../.."><code>libcult</code></a> <code>/</code>
+<a href=".."><code>documentation</code></a> <code>/</code>
+<code>mm</code>
+</p>
+</div>
+
+<div id="content">
+<p>The <em>libcult</em> memory management library provides
+non-intrusive reference counter and a couple of smart pointers.</p>
+
+<p>It also overrides and overloads default memory management operators
+(<code>operator new</code> and <code>operator delete</code>) to allow
+special service objects (reference counter being one of them) to be
+constructed in the memory block preceding the instance. This allows
+transparent <em>instrumentation</em> of objects with a special
+functionality like reference counting or locking.</p>
+
+<p>The two flavors of smart pointers are exclusive (called
+<code>Evptr</code>, from <b>e</b>xclusi<b>v</b>e
+<b>p</b>oin<b>t</b>e<b>r</b>) and shared (called <code>Shptr</code>,
+from <b>sh</b>ared <b>p</b>oin<b>t</b>e<b>r</b>) pointers.</p>
+
+<p>The exclusive pointer has semantics similar to <code>std::auto_ptr</code>
+(i.e., exclusive ownership of the object pointed to) except that it performs
+automatic copying of the object pointed to when copied or assigned to another
+exclusive pointer. Built-in copy-on-write optimization eliminates unnecessary
+copying when instances of exclusive pointers are returned from functions or
+stored in containers.</p>
+
+<p>The shared pointer has standard semantics of a reference-counting smart
+pointer.</p>
+</div>
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/documentation/os/index.xhtml b/libcult/documentation/os/index.xhtml
new file mode 100644
index 0000000..62914fa
--- /dev/null
+++ b/libcult/documentation/os/index.xhtml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/os/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation/os</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="libcult,os,net"/>
+ <meta name="description" content="libcult/documentation/os"/>
+
+ <link rel="stylesheet" type="text/css" href="../default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href="../.."><code>libcult</code></a> <code>/</code>
+<a href=".."><code>documentation</code></a> <code>/</code>
+<code>os</code>
+</p>
+</div>
+
+<div id="content">
+<p>The <em>libcult</em> operating system library provides an object-oriented
+interface to the OS primitives as defined by the Single
+UNIX Specification. Only basic networking is supported in this
+version.</p>
+</div>
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/documentation/rtti/index.xhtml b/libcult/documentation/rtti/index.xhtml
new file mode 100644
index 0000000..ff3238c
--- /dev/null
+++ b/libcult/documentation/rtti/index.xhtml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/rtti/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation/rtti</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="libcult,c++,rtti,run-time,type,information"/>
+ <meta name="description" content="libcult/documentation/rtti"/>
+
+ <link rel="stylesheet" type="text/css" href="../default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href="../.."><code>libcult</code></a> <code>/</code>
+<a href=".."><code>documentation</code></a> <code>/</code>
+<code>rtti</code>
+</p>
+</div>
+
+<div id="content">
+<p>The <em>libcult</em> run-time type information (rtti) library provides
+a convenience wrapper around <code>std::type_info</code> as well as
+facilities for optional extended type information (e.g., inheritance
+graph).</p>
+</div>
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/documentation/sched/index.xhtml b/libcult/documentation/sched/index.xhtml
new file mode 100644
index 0000000..b685471
--- /dev/null
+++ b/libcult/documentation/sched/index.xhtml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/sched/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation/sched</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="libcult,c++,scheduling,thread,lock,mutex"/>
+ <meta name="description" content="libcult/documentation/sched"/>
+
+ <link rel="stylesheet" type="text/css" href="../default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href="../.."><code>libcult</code></a> <code>/</code>
+<a href=".."><code>documentation</code></a> <code>/</code>
+<code>sched</code>
+</p>
+</div>
+
+<div id="content">
+<p>The <em>libcult</em> scheduling library provides an object-oriented
+interface to POSIX thread primitives as defined by the Single
+UNIX Specification.</p>
+</div>
+
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/documentation/trace/index.xhtml b/libcult/documentation/trace/index.xhtml
new file mode 100644
index 0000000..eb00f04
--- /dev/null
+++ b/libcult/documentation/trace/index.xhtml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/trace/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation/trace</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="libcult,c++,tracing"/>
+ <meta name="description" content="libcult/documentation/trace"/>
+
+ <link rel="stylesheet" type="text/css" href="../default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href="../.."><code>libcult</code></a> <code>/</code>
+<a href=".."><code>documentation</code></a> <code>/</code>
+<code>trace</code>
+</p>
+</div>
+
+<div id="content">
+<p>The <em>libcult</em> trace library provides a general-purpose
+program tracing facility. The following code fragment can be found
+in <code>libcult/examples/trace</code>:</p>
+
+<pre class="cxx">
+struct foo {};
+
+std::ostream&amp;
+operator&lt;&lt; (std::ostream&amp; o, foo const&amp;)
+{
+ return o &lt;&lt; "::foo";
+}
+
+namespace trace = cult::trace;
+
+trace::stream tout ("main", 4);
+
+int
+main ()
+{
+ using trace::record;
+
+ trace::log::instance ().level (9);
+
+ record a ("main", 2);
+ a &lt;&lt; "notationally burdensome";
+ tout &lt;&lt; a;
+
+ record b ("main", 2);
+ tout &lt;&lt; (b &lt;&lt; "a bit better, but still burdensome");
+
+ tout &lt;&lt; (record ("main", 2) &lt;&lt; "this is"
+ &lt;&lt; " somewhat"
+ &lt;&lt; " twisted but nice to be able to");
+
+ tout &lt;&lt; "concise, using default level";
+
+ tout &lt;&lt; 9 &lt;&lt; "concise, using custom level";
+
+ foo f;
+
+ tout &lt;&lt; 3 &lt;&lt; f &lt;&lt; " " &lt;&lt; 5;
+}
+</pre>
+
+<p>Along with the proper implementation, a <em>null</em> implementation is
+provided which can be used to completely optimize trace code away. For details
+see the <a href="http://kolpackov.net/pipermail/notes/2004-July/000010.html">
+Inlining code away</a> essay.</p>
+</div>
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/documentation/types/index.xhtml b/libcult/documentation/types/index.xhtml
new file mode 100644
index 0000000..07cb7db
--- /dev/null
+++ b/libcult/documentation/types/index.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/types/index.xhtml
+author : Boris Kolpackov <boris@kolpackov.net>
+copyright : Copyright (c) 2005-2010 Boris Kolpackov
+license : GNU FDL v1.2; http://kolpackov.net/licenses/fdl-1.2.txt
+
+-->
+
+<head>
+
+ <title>libcult/documentation/types</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2005-2010 Boris Kolpackov"/>
+ <meta name="keywords" content="libcult,c++,types"/>
+ <meta name="description" content="libcult/documentation/types"/>
+
+ <link rel="stylesheet" type="text/css" href="../default.css"/>
+
+</head>
+
+<body>
+
+<div id="navigation">
+<p>
+<a href="../.."><code>libcult</code></a> <code>/</code>
+<a href=".."><code>documentation</code></a> <code>/</code>
+<code>types</code>
+</p>
+</div>
+
+<div id="content">
+<p>The <em>libcult</em> type library provides convenience aliases
+for basic c++ types (e.g., <code>wchar</code> and <code>size</code>)
+as well as a set of fixed-size integer types.</p>
+</div>
+
+<div id="docinfo">
+<p>Copyright &copy; 2005-2010 <a title="Boris Kolpackov"
+href="http://kolpackov.net">Boris Kolpackov</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://kolpackov.net/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>
diff --git a/libcult/examples/cli/cli.cxx b/libcult/examples/cli/cli.cxx
new file mode 100644
index 0000000..922a23d
--- /dev/null
+++ b/libcult/examples/cli/cli.cxx
@@ -0,0 +1,65 @@
+// file : examples/cli/cli.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/types.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+#include <cult/cli/options-parser.hxx>
+
+#include <iostream>
+
+using std::cerr;
+using std::endl;
+
+using namespace Cult;
+
+namespace
+{
+ extern Char const help[] = "help";
+ extern Char const version[] = "version";
+ extern Char const outdir[] = "outdir";
+}
+
+typedef
+CLI::Options<help, Boolean,
+ version, Boolean,
+ outdir, String>
+Options;
+
+Int
+main (Int argc, Char* argv[])
+{
+ try
+ {
+ Options options (CLI::parse<Options> (argc, argv));
+
+ if (options.value<help> ())
+ {
+ cerr << "usage: " << argv[0] << " [--help] [--version] [--outdir <dir>]"
+ << endl;
+ return 0;
+ }
+
+ if (options.value<version> ())
+ {
+ cerr << argv[0] << " 1.2.3" << endl;
+ return 0;
+ }
+
+ if (String dir = options.value<outdir> ())
+ {
+ cerr << "outdir: " << dir << endl;
+ }
+ }
+ catch (CLI::UnexpectedOption const& e)
+ {
+ cerr << "unexpected option " << e.option () <<endl;
+ }
+ catch (CLI::OptionFormat const& e)
+ {
+ cerr << "bad format for " << e.option () << endl;
+ }
+}
diff --git a/libcult/examples/cli/makefile b/libcult/examples/cli/makefile
new file mode 100644
index 0000000..004f135
--- /dev/null
+++ b/libcult/examples/cli/makefile
@@ -0,0 +1,48 @@
+# file : examples/cli/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make
+
+cxx_tun := cli.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cult.l := $(out_root)/cult/cult.l
+cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options
+
+cli := $(out_base)/cli
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(cli): $(cxx_obj) $(cult.l)
+
+$(cxx_obj) $(cxx_od): $(cult.l.cpp-options)
+
+$(call include-dep,$(cxx_od))
+
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(cli)
+
+
+# Clean.
+#
+$(clean): $(cli).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/cult/makefile)
diff --git a/libcult/examples/dr/xdr/makefile b/libcult/examples/dr/xdr/makefile
new file mode 100644
index 0000000..6a4fa8f
--- /dev/null
+++ b/libcult/examples/dr/xdr/makefile
@@ -0,0 +1,49 @@
+# file : examples/dr/xdr/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make
+
+cxx_tun := xdr.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cult.l := $(out_root)/cult/cult.l
+cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options
+
+xdr := $(out_base)/xdr
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(xdr): $(cxx_obj) $(cult.l)
+
+$(cxx_obj) $(cxx_od): $(cult.l.cpp-options)
+
+$(call include-dep,$(cxx_od))
+
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(xdr)
+
+
+# Clean.
+#
+$(clean): $(xdr).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/cult/makefile)
diff --git a/libcult/examples/dr/xdr/xdr.cxx b/libcult/examples/dr/xdr/xdr.cxx
new file mode 100644
index 0000000..38e948d
--- /dev/null
+++ b/libcult/examples/dr/xdr/xdr.cxx
@@ -0,0 +1,87 @@
+// file : examples/dr/xdr/xdr.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/types.hxx>
+
+#include <cult/dr/xdr/input-stream.hxx>
+#include <cult/dr/xdr/output-stream.hxx>
+
+#include <iostream>
+
+using namespace Cult;
+using namespace DR::XDR;
+
+using std::cerr;
+using std::endl;
+
+Int
+main ()
+{
+ try
+ {
+ OutputStream o (8);
+
+ o << true << false;
+
+ UnsignedInt8 a8 (0xDE);
+ UnsignedInt16 a16 (0xDEAD);
+ UnsignedInt32 a32 (0xDEADBEEF);
+ UnsignedInt64 a64 (0xDEADBEEFDEADBEEFULL);
+
+ o << a8 << a16 << a32 << a64;
+
+ Int8 b8 (-8);
+ Int16 b16 (-16);
+ Int32 b32 (-32);
+ Int64 b64 (-64);
+
+ o << b8 << b16 << b32 << b64;
+
+ String s ("reasonably loooooooooooooong string with some junk in it");
+
+ o << s;
+
+ InputStream i (o.buffer ());
+
+ Boolean t, f;
+ String s1;
+
+ i >> t >> f;
+ i >> a8 >> a16 >> a32 >> a64;
+ i >> b8 >> b16 >> b32 >> b64;
+ i >> s1;
+
+ if (!t
+ || f
+ || a8 != 0xDE
+ || a16 != 0xDEAD
+ || a32 != 0xDEADBEEF
+ || a64 != 0xDEADBEEFDEADBEEFULL
+ || b8 != -8
+ || b16 != -16
+ || b32 != -32
+ || b64 != -64
+ || s1 != s) return 1;
+
+ try
+ {
+ i >> t;
+ }
+ catch (Extraction const&)
+ {
+ return 0;
+ }
+ }
+ catch (Insertion const&)
+ {
+ cerr << "insertion" << endl;
+ }
+ catch (Extraction const&)
+ {
+ cerr << "extraction" << endl;
+ }
+
+ return 1;
+}
diff --git a/libcult/examples/makefile b/libcult/examples/makefile
new file mode 100644
index 0000000..d264910
--- /dev/null
+++ b/libcult/examples/makefile
@@ -0,0 +1,36 @@
+# file : examples/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+include $(scf_root)/configuration.make
+
+default := $(out_base)/
+clean := $(out_base)/.clean
+
+examples := $(out_base)/cli \
+ $(out_base)/mm/shptr \
+ $(out_base)/mm/transfer \
+ $(out_base)/trace
+
+ifeq ($(cult_threads),y)
+examples += $(out_base)/sched/main \
+ $(out_base)/sched/cancel
+endif
+
+
+ifeq ($(cult_network),y)
+examples += $(out_base)/os/net/ipv4/datagram \
+ $(out_base)/os/net/ipv4/multicast
+endif
+
+ifeq ($(cult_dr),y)
+examples += $(out_base)/dr/xdr
+endif
+
+
+$(default): $(addsuffix /,$(examples))
+$(clean): $(addsuffix /.clean,$(examples))
+
+$(foreach e,$(subst $(out_base),$(src_base),$(examples)),$(call import,$e/makefile))
diff --git a/libcult/examples/mm/shptr/makefile b/libcult/examples/mm/shptr/makefile
new file mode 100644
index 0000000..2bf1598
--- /dev/null
+++ b/libcult/examples/mm/shptr/makefile
@@ -0,0 +1,48 @@
+# file : examples/mm/shptr/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make
+
+cxx_tun := shptr.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cult.l := $(out_root)/cult/cult.l
+cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options
+
+shptr := $(out_base)/shptr
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(shptr): $(cxx_obj) $(cult.l)
+
+$(cxx_obj) $(cxx_od): $(cult.l.cpp-options)
+
+$(call include-dep,$(cxx_od))
+
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(shptr)
+
+
+# Clean.
+#
+$(clean): $(shptr).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/cult/makefile)
diff --git a/libcult/examples/mm/shptr/shptr.cxx b/libcult/examples/mm/shptr/shptr.cxx
new file mode 100644
index 0000000..cb026d4
--- /dev/null
+++ b/libcult/examples/mm/shptr/shptr.cxx
@@ -0,0 +1,73 @@
+// file : examples/mm/shptr/shptr.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/mm/shptr.hxx>
+#include <cult/mm/new.hxx> // MM::locate
+#include <cult/mm/counter.hxx> // MM::inc_ref
+
+#include <iostream>
+
+using std::cerr;
+using std::endl;
+
+using namespace Cult;
+using namespace MM;
+
+struct Foo
+{
+ virtual ~Foo () {}
+ char c;
+};
+
+struct Bar: virtual Foo {char c;};
+
+struct Baz: virtual Foo {char c;};
+
+struct Fox: Bar, Baz {};
+
+
+struct A
+{
+ char c[8];
+};
+
+struct B
+{
+ char c[8];
+};
+
+struct C : A, B
+{
+ char c[8];
+};
+
+int
+main ()
+{
+ {
+ Baz* bp (new Fox);
+ Foo* fp (bp);
+
+ Counter* cp (locate (fp, *counted));
+
+ inc_ref (bp);
+
+ cp->dec_ref ();
+
+ if (cp->dec_ref ()) cerr << "good: destroying" << endl;
+ else cerr << "bad: leaking" << endl;
+
+ delete bp;
+ }
+
+ {
+ Shptr<Fox> pfox (new Fox);
+ Shptr<Bar> pbar (pfox);
+
+ Shptr<Foo> pfoo;
+
+ pfoo = pbar;
+ }
+}
diff --git a/libcult/examples/mm/transfer/makefile b/libcult/examples/mm/transfer/makefile
new file mode 100644
index 0000000..3380f10
--- /dev/null
+++ b/libcult/examples/mm/transfer/makefile
@@ -0,0 +1,48 @@
+# file : examples/mm/transfer/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make
+
+cxx_tun := transfer.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cult.l := $(out_root)/cult/cult.l
+cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options
+
+transfer := $(out_base)/transfer
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(transfer): $(cxx_obj) $(cult.l)
+
+$(cxx_obj) $(cxx_od): $(cult.l.cpp-options)
+
+$(call include-dep,$(cxx_od))
+
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(transfer)
+
+
+# Clean.
+#
+$(clean): $(transfer).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/cult/makefile)
diff --git a/libcult/examples/mm/transfer/transfer.cxx b/libcult/examples/mm/transfer/transfer.cxx
new file mode 100644
index 0000000..81014d0
--- /dev/null
+++ b/libcult/examples/mm/transfer/transfer.cxx
@@ -0,0 +1,117 @@
+// file : examples/mm/transfer/transfer.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/mm/evptr.hxx>
+
+#include <iostream>
+
+using std::cerr;
+using std::endl;
+
+using namespace Cult;
+
+unsigned long count = 0;
+unsigned long clone_count = 0;
+
+struct Type
+{
+ Type ()
+ {
+ ++count;
+ }
+
+ ~Type ()
+ {
+ --count;
+ }
+
+ Evptr<Type>
+ clone () const
+ {
+ ++clone_count;
+ return Evptr<Type> (new Type);
+ }
+
+ Void
+ f () const
+ {
+ Int i = i_;
+ ++i;
+ }
+
+ Int i_;
+};
+
+
+Evptr<Type>
+source ()
+{
+ return Evptr<Type> (new Type);
+}
+
+Void
+sink (Evptr<Type> a, Boolean r = true)
+{
+ if (r)
+ {
+ sink (a, false);
+ }
+ else
+ {
+ Evptr<Type> b (a);
+
+ cerr << "\tshare count: " << b.count () << endl;
+
+ // Any of these will trigger cloning.
+ //
+ b->f ();
+ }
+}
+
+Int
+main ()
+{
+ // case 1
+ //
+ {
+ cerr << "sink (new type)" << endl;
+
+ clone_count = 0;
+ sink (new Type);
+
+ cerr << "\tclone count: " << clone_count << endl
+ << endl;
+ }
+
+ // case 2
+ //
+ {
+ cerr << "sink (source ())" << endl;
+
+ clone_count = 0;
+ sink (source ());
+
+ cerr << "\tclone count: " << clone_count << endl
+ << endl;
+ }
+
+
+ // case 3
+ //
+ {
+ cerr << "sink (p)" << endl;
+
+ clone_count = 0;
+
+ Evptr<Type> p (new Type);
+ sink (p);
+
+ cerr << "\tclone count: " << clone_count << endl
+ << endl;
+ }
+
+
+ cerr << "balance: " << count << endl;
+}
diff --git a/libcult/examples/os/net/ipv4/datagram/client.cxx b/libcult/examples/os/net/ipv4/datagram/client.cxx
new file mode 100644
index 0000000..863fc25
--- /dev/null
+++ b/libcult/examples/os/net/ipv4/datagram/client.cxx
@@ -0,0 +1,66 @@
+// file : examples/os/net/ipv4/datagram/client.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/types.hxx>
+
+#include <cult/os/net/ipv4/address.hxx>
+#include <cult/os/net/ipv4/datagram-socket.hxx>
+
+#include <iostream>
+#include <unistd.h> // usleep
+
+#include "protocol.hxx"
+
+using std::cerr;
+using std::endl;
+
+using namespace Cult;
+using namespace OS::Net::IPv4;
+
+class Args {};
+
+Int
+main (Int argc, Char* argv[])
+{
+ try
+ {
+ if (argc < 2)
+ throw Args ();
+
+ Address addr (argv[1], 10000);
+
+ DatagramSocket socket;
+
+ Message msg;
+ msg.sn = 0;
+
+ cerr << "message size : " << sizeof (msg) << " bytes" << endl;
+ cerr << "send buffer : " << socket.send_buffer_size () << " bytes" << endl;
+
+ for (Index i = 0; i < payload_size; i++)
+ {
+ msg.payload[i] = i;
+ }
+
+ for (; msg.sn < message_count; msg.sn++)
+ {
+ socket.send (&msg, sizeof (msg), addr);
+
+ // ::usleep (10);
+ }
+
+ return 0;
+ }
+ catch (OS::Exception const& e)
+ {
+ cerr << "errno: " << strerror (e.code ()) << endl;
+ }
+ catch (Args const&)
+ {
+ cerr << "usage: client <IPv4 address>" << endl;
+ }
+
+ return 1;
+}
diff --git a/libcult/examples/os/net/ipv4/datagram/makefile b/libcult/examples/os/net/ipv4/datagram/makefile
new file mode 100644
index 0000000..2dc8e1b
--- /dev/null
+++ b/libcult/examples/os/net/ipv4/datagram/makefile
@@ -0,0 +1,55 @@
+# file : examples/os/net/ipv4/datagram/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make
+
+client_cxx_tun := client.cxx
+server_cxx_tun := server.cxx
+
+client_cxx_obj := $(addprefix $(out_base)/,$(client_cxx_tun:.cxx=.o))
+server_cxx_obj := $(addprefix $(out_base)/,$(server_cxx_tun:.cxx=.o))
+
+cxx_obj := $(client_cxx_obj) $(server_cxx_obj)
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cult.l := $(out_root)/cult/cult.l
+cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options
+
+client := $(out_base)/client
+server := $(out_base)/server
+clean := $(out_base)/.clean
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(client) $(server)
+
+# Build.
+#
+
+$(client): $(client_cxx_obj) $(cult.l)
+$(server): $(server_cxx_obj) $(cult.l)
+
+$(cxx_obj) $(cxx_od): $(cult.l.cpp-options)
+
+$(call include-dep,$(cxx_od))
+
+
+# Clean.
+#
+$(clean): $(client).o.clean \
+ $(server).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/cult/makefile)
diff --git a/libcult/examples/os/net/ipv4/datagram/protocol.hxx b/libcult/examples/os/net/ipv4/datagram/protocol.hxx
new file mode 100644
index 0000000..0f418e8
--- /dev/null
+++ b/libcult/examples/os/net/ipv4/datagram/protocol.hxx
@@ -0,0 +1,20 @@
+// file : examples/os/net/ipv4/datagram/protocol.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef PROTOCOL_HXX
+#define PROTOCOL_HXX
+
+#include <cult/types.hxx>
+
+Cult::UnsignedShort const payload_size = 256;
+Cult::UnsignedLong const message_count = 100;
+
+struct Message
+{
+ Cult::UnsignedLong sn;
+ Cult::UnsignedShort payload[payload_size];
+};
+
+#endif // PROTOCOL_HXX
diff --git a/libcult/examples/os/net/ipv4/datagram/server.cxx b/libcult/examples/os/net/ipv4/datagram/server.cxx
new file mode 100644
index 0000000..e788056
--- /dev/null
+++ b/libcult/examples/os/net/ipv4/datagram/server.cxx
@@ -0,0 +1,123 @@
+// file : examples/os/net/ipv4/datagram/server.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/types.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <cult/os/net/ipv4/address.hxx>
+#include <cult/os/net/ipv4/datagram-socket.hxx>
+
+#include <iostream>
+#include <cstring> // memcmp
+
+#include "protocol.hxx"
+
+using std::cerr;
+using std::endl;
+
+using namespace Cult;
+using namespace OS::Net::IPv4;
+
+typedef Containers::Vector<Boolean> StatusList;
+
+Int
+main ()
+{
+ try
+ {
+ Address addr (INADDR_ANY, 10000);
+
+ DatagramSocket socket (addr);
+
+ Message expected_msg;
+ expected_msg.sn = 0;
+
+ for (UnsignedShort i = 0; i < payload_size; ++i)
+ {
+ expected_msg.payload[i] = i;
+ }
+
+ StatusList received (message_count, 0);
+ StatusList damaged (message_count, 0);
+ StatusList duplicate (message_count, 0);
+
+ Message msg;
+
+ while (true)
+ {
+ socket.recv (&msg, sizeof (msg));
+
+ if (received[msg.sn])
+ {
+ duplicate[msg.sn] = true;
+ }
+ else
+ {
+ received[msg.sn] = true;
+
+ if (std::memcmp (expected_msg.payload, msg.payload, payload_size) != 0)
+ {
+ damaged[msg.sn] = true;
+ }
+ }
+
+ if (msg.sn + 1 == message_count) break;
+ }
+
+ UnsignedLong lost_count (0), damaged_count (0), duplicate_count (0);
+
+ for (StatusList::Iterator i (received.begin ()), end (received.end ());
+ i != end;
+ ++i)
+ if (!*i) ++lost_count;
+
+ for (StatusList::Iterator i (damaged.begin ()), end (damaged.end ());
+ i != end;
+ ++i)
+ if (*i) ++damaged_count;
+
+ for (StatusList::Iterator i (duplicate.begin ()), end (duplicate.end ());
+ i != end;
+ ++i)
+ if (*i) ++duplicate_count;
+
+ cerr << "lost : " << lost_count << endl
+ << "damaged : " << damaged_count << endl
+ << "duplicate : " << duplicate_count << endl << endl;
+
+ if (lost_count != 0)
+ {
+ cerr << "lost message dump:" << endl;
+
+ UnsignedLong total = 0;
+
+ for (StatusList::Iterator
+ begin (received.begin ()), i (begin), end (received.end ());
+ i != end;)
+ {
+ if (!*i)
+ {
+ UnsignedLong count = 1;
+
+ for (StatusList::Iterator j = i + 1; j < end && !*j; j++, count++) ;
+
+ cerr << '\t' << i - begin << " : " << count << endl;
+
+ i += count;
+ total += count;
+ }
+ else
+ ++i;
+ }
+
+ if (total != lost_count)
+ cerr << "trouble" << endl;
+ }
+ }
+ catch (OS::Exception const& e)
+ {
+ cerr << "errno: " << e.code () << endl;
+ }
+}
diff --git a/libcult/examples/os/net/ipv4/multicast/client.cxx b/libcult/examples/os/net/ipv4/multicast/client.cxx
new file mode 100644
index 0000000..863fc25
--- /dev/null
+++ b/libcult/examples/os/net/ipv4/multicast/client.cxx
@@ -0,0 +1,66 @@
+// file : examples/os/net/ipv4/datagram/client.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/types.hxx>
+
+#include <cult/os/net/ipv4/address.hxx>
+#include <cult/os/net/ipv4/datagram-socket.hxx>
+
+#include <iostream>
+#include <unistd.h> // usleep
+
+#include "protocol.hxx"
+
+using std::cerr;
+using std::endl;
+
+using namespace Cult;
+using namespace OS::Net::IPv4;
+
+class Args {};
+
+Int
+main (Int argc, Char* argv[])
+{
+ try
+ {
+ if (argc < 2)
+ throw Args ();
+
+ Address addr (argv[1], 10000);
+
+ DatagramSocket socket;
+
+ Message msg;
+ msg.sn = 0;
+
+ cerr << "message size : " << sizeof (msg) << " bytes" << endl;
+ cerr << "send buffer : " << socket.send_buffer_size () << " bytes" << endl;
+
+ for (Index i = 0; i < payload_size; i++)
+ {
+ msg.payload[i] = i;
+ }
+
+ for (; msg.sn < message_count; msg.sn++)
+ {
+ socket.send (&msg, sizeof (msg), addr);
+
+ // ::usleep (10);
+ }
+
+ return 0;
+ }
+ catch (OS::Exception const& e)
+ {
+ cerr << "errno: " << strerror (e.code ()) << endl;
+ }
+ catch (Args const&)
+ {
+ cerr << "usage: client <IPv4 address>" << endl;
+ }
+
+ return 1;
+}
diff --git a/libcult/examples/os/net/ipv4/multicast/makefile b/libcult/examples/os/net/ipv4/multicast/makefile
new file mode 100644
index 0000000..cb35bf6
--- /dev/null
+++ b/libcult/examples/os/net/ipv4/multicast/makefile
@@ -0,0 +1,55 @@
+# file : examples/os/net/ipv4/multicast/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make
+
+client_cxx_tun := client.cxx
+server_cxx_tun := server.cxx
+
+client_cxx_obj := $(addprefix $(out_base)/,$(client_cxx_tun:.cxx=.o))
+server_cxx_obj := $(addprefix $(out_base)/,$(server_cxx_tun:.cxx=.o))
+
+cxx_obj := $(client_cxx_obj) $(server_cxx_obj)
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cult.l := $(out_root)/cult/cult.l
+cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options
+
+client := $(out_base)/client
+server := $(out_base)/server
+clean := $(out_base)/.clean
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(client) $(server)
+
+# Build.
+#
+
+$(client): $(client_cxx_obj) $(cult.l)
+$(server): $(server_cxx_obj) $(cult.l)
+
+$(cxx_obj) $(cxx_od): $(cult.l.cpp-options)
+
+$(call include-dep,$(cxx_od))
+
+
+# Clean.
+#
+$(clean): $(client).o.clean \
+ $(server).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/cult/makefile)
diff --git a/libcult/examples/os/net/ipv4/multicast/protocol.hxx b/libcult/examples/os/net/ipv4/multicast/protocol.hxx
new file mode 100644
index 0000000..a4057de
--- /dev/null
+++ b/libcult/examples/os/net/ipv4/multicast/protocol.hxx
@@ -0,0 +1,20 @@
+// file : examples/os/net/ipv4/multicast/protocol.hxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef PROTOCOL_HXX
+#define PROTOCOL_HXX
+
+#include <cult/types.hxx>
+
+Cult::UnsignedShort const payload_size = 256;
+Cult::UnsignedLong const message_count = 100;
+
+struct Message
+{
+ Cult::UnsignedLong sn;
+ Cult::UnsignedShort payload[payload_size];
+};
+
+#endif // PROTOCOL_HXX
diff --git a/libcult/examples/os/net/ipv4/multicast/server.cxx b/libcult/examples/os/net/ipv4/multicast/server.cxx
new file mode 100644
index 0000000..5d8fe99
--- /dev/null
+++ b/libcult/examples/os/net/ipv4/multicast/server.cxx
@@ -0,0 +1,134 @@
+// file : examples/os/net/ipv4/datagram/server.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/types.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <cult/os/net/ipv4/address.hxx>
+#include <cult/os/net/ipv4/multicast-socket.hxx>
+
+#include <iostream>
+#include <cstring> // memcmp
+
+#include "protocol.hxx"
+
+using std::cerr;
+using std::endl;
+
+using namespace Cult;
+using namespace OS::Net::IPv4;
+
+typedef Containers::Vector<Boolean> StatusList;
+
+class Args {};
+
+Int
+main (Int argc, Char* argv[])
+{
+ try
+ {
+ if (argc < 2)
+ throw Args ();
+
+ Address addr (argv[1], 10000);
+
+ MulticastSocket socket;
+
+ socket.join (addr);
+
+ Message expected_msg;
+ expected_msg.sn = 0;
+
+ for (UnsignedShort i = 0; i < payload_size; ++i)
+ {
+ expected_msg.payload[i] = i;
+ }
+
+ StatusList received (message_count, 0);
+ StatusList damaged (message_count, 0);
+ StatusList duplicate (message_count, 0);
+
+ Message msg;
+
+ while (true)
+ {
+ socket.recv (&msg, sizeof (msg));
+
+ if (received[msg.sn])
+ {
+ duplicate[msg.sn] = true;
+ }
+ else
+ {
+ received[msg.sn] = true;
+
+ if (std::memcmp (expected_msg.payload, msg.payload, payload_size) != 0)
+ {
+ damaged[msg.sn] = true;
+ }
+ }
+
+ if (msg.sn + 1 == message_count) break;
+ }
+
+ UnsignedLong lost_count (0), damaged_count (0), duplicate_count (0);
+
+ for (StatusList::Iterator i (received.begin ()), end (received.end ());
+ i != end;
+ ++i)
+ if (!*i) ++lost_count;
+
+ for (StatusList::Iterator i (damaged.begin ()), end (damaged.end ());
+ i != end;
+ ++i)
+ if (*i) ++damaged_count;
+
+ for (StatusList::Iterator i (duplicate.begin ()), end (duplicate.end ());
+ i != end;
+ ++i)
+ if (*i) ++duplicate_count;
+
+ cerr << "lost : " << lost_count << endl
+ << "damaged : " << damaged_count << endl
+ << "duplicate : " << duplicate_count << endl << endl;
+
+ if (lost_count != 0)
+ {
+ cerr << "lost message dump:" << endl;
+
+ UnsignedLong total = 0;
+
+ for (StatusList::Iterator
+ begin (received.begin ()), i (begin), end (received.end ());
+ i != end;)
+ {
+ if (!*i)
+ {
+ UnsignedLong count = 1;
+
+ for (StatusList::Iterator j = i + 1; j < end && !*j; j++, count++) ;
+
+ cerr << '\t' << i - begin << " : " << count << endl;
+
+ i += count;
+ total += count;
+ }
+ else
+ ++i;
+ }
+
+ if (total != lost_count)
+ cerr << "trouble" << endl;
+ }
+ }
+ catch (OS::Exception const& e)
+ {
+ cerr << "errno: " << e.code () << endl;
+ }
+ catch (Args const&)
+ {
+ cerr << "usage: client <IPv4 address>" << endl;
+ }
+}
diff --git a/libcult/examples/sched/cancel/cancel.cxx b/libcult/examples/sched/cancel/cancel.cxx
new file mode 100644
index 0000000..ee71449
--- /dev/null
+++ b/libcult/examples/sched/cancel/cancel.cxx
@@ -0,0 +1,63 @@
+// file : examples/sched/cancel/cancel.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/types.hxx>
+
+#include <cult/mm/shptr.hxx>
+
+#include <cult/sched/lock.hxx>
+#include <cult/sched/mutex.hxx>
+#include <cult/sched/thread.hxx>
+#include <cult/sched/condition.hxx>
+
+
+#include <iostream>
+#include <unistd.h> // sleep
+
+using std::cerr;
+using std::endl;
+
+using namespace Cult;
+using namespace Sched;
+
+Void*
+cond_wait_thread_proc (Void*)
+{
+ try
+ {
+ Mutex mutex;
+ Condition cond (mutex);
+
+ Lock lock (mutex);
+
+ cond.wait ();
+ }
+ /*
+ catch (std::thread_canceled const& e)
+ {
+ cerr << "caught thread_canceled" << endl;
+ throw;
+ }
+ */
+ catch (...)
+ {
+ cerr << "presumably caught thread_canceled" << endl;
+ throw;
+ }
+
+ return 0;
+}
+
+
+Int
+main ()
+{
+ Shptr<Thread> thread (new Thread (cond_wait_thread_proc));
+
+ sleep (1);
+
+ thread->cancel ();
+ thread->join ();
+}
diff --git a/libcult/examples/sched/cancel/makefile b/libcult/examples/sched/cancel/makefile
new file mode 100644
index 0000000..38a96bd
--- /dev/null
+++ b/libcult/examples/sched/cancel/makefile
@@ -0,0 +1,48 @@
+# file : examples/sched/cancel/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make
+
+cxx_tun := cancel.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cult.l := $(out_root)/cult/cult.l
+cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options
+
+cancel := $(out_base)/cancel
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(cancel): $(cxx_obj) $(cult.l)
+
+$(cxx_obj) $(cxx_od): $(cult.l.cpp-options)
+
+$(call include-dep,$(cxx_od))
+
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(cancel)
+
+
+# clean
+#
+$(clean): $(cancel).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/cult/makefile)
diff --git a/libcult/examples/sched/main/main.cxx b/libcult/examples/sched/main/main.cxx
new file mode 100644
index 0000000..58cc2cc
--- /dev/null
+++ b/libcult/examples/sched/main/main.cxx
@@ -0,0 +1,43 @@
+// file : examples/sched/main/main.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/types.hxx>
+
+#include <cult/mm/shptr.hxx>
+#include <cult/sched/thread.hxx>
+
+#include <iostream>
+#include <unistd.h> // sleep
+
+using namespace Cult;
+using namespace Sched;
+
+using std::cerr;
+using std::endl;
+
+Void*
+thread_func (Void*)
+{
+ cerr << "second thread: going to sleep for a few seconds" << endl;
+
+ sleep (2);
+
+ cerr << "second thread: woke up, now exiting" << endl;
+
+ return 0;
+}
+
+
+Int
+main ()
+{
+ Shptr<Thread> self (new Thread);
+
+ Shptr<Thread> other (new Thread (thread_func));
+
+ cerr << "initial thread: exiting" << endl;
+
+ Thread::exit (0);
+}
diff --git a/libcult/examples/sched/main/makefile b/libcult/examples/sched/main/makefile
new file mode 100644
index 0000000..945237f
--- /dev/null
+++ b/libcult/examples/sched/main/makefile
@@ -0,0 +1,48 @@
+# file : examples/sched/main/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make
+
+cxx_tun := main.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cult.l := $(out_root)/cult/cult.l
+cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options
+
+main := $(out_base)/main
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(main): $(cxx_obj) $(cult.l)
+
+$(cxx_obj) $(cxx_od): $(cult.l.cpp-options)
+
+$(call include-dep,$(cxx_od))
+
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(main)
+
+
+# Clean.
+#
+$(clean): $(main).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/cult/makefile)
diff --git a/libcult/examples/trace/makefile b/libcult/examples/trace/makefile
new file mode 100644
index 0000000..57e2b7b
--- /dev/null
+++ b/libcult/examples/trace/makefile
@@ -0,0 +1,48 @@
+# file : examples/trace/makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make
+
+cxx_tun := trace.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cult.l := $(out_root)/cult/cult.l
+cult.l.cpp-options := $(out_root)/cult/cult.l.cpp-options
+
+trace := $(out_base)/trace
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(trace): $(cxx_obj) $(cult.l)
+
+$(cxx_obj) $(cxx_od): $(cult.l.cpp-options)
+
+$(call include-dep,$(cxx_od))
+
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(trace)
+
+
+# Clean.
+#
+$(clean): $(trace).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/cult/makefile)
diff --git a/libcult/examples/trace/trace.cxx b/libcult/examples/trace/trace.cxx
new file mode 100644
index 0000000..e2a09d4
--- /dev/null
+++ b/libcult/examples/trace/trace.cxx
@@ -0,0 +1,51 @@
+// file : examples/trace/trace.cxx
+// author : Boris Kolpackov <boris@kolpackov.net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/types.hxx>
+
+#include <cult/trace/log.hxx>
+#include <cult/trace/record.hxx>
+#include <cult/trace/stream.hxx>
+
+#include <ostream>
+
+using namespace Cult;
+
+struct Foo {};
+
+std::ostream&
+operator<< (std::ostream& o, Foo const&)
+{
+ return o << "::Foo";
+}
+
+Trace::Stream tout ("Examples::Trace", 4);
+
+Int
+main ()
+{
+ using Trace::Record;
+
+ Trace::Log::instance ().level (9);
+
+ Record a ("main", 2);
+ a << "notationally burdensome";
+ tout << a;
+
+ Record b ("main", 2);
+ tout << (b << "a bit better, but still burdensome");
+
+ tout << (Record ("main", 2) << "this is"
+ << " somewhat"
+ << " twisted but nice to be able to");
+
+ tout << "concise, using default level";
+
+ tout << 9 << "concise, using custom level";
+
+ Foo f;
+
+ tout << 3 << f << " " << 5;
+}
diff --git a/libcult/makefile b/libcult/makefile
new file mode 100644
index 0000000..64c9286
--- /dev/null
+++ b/libcult/makefile
@@ -0,0 +1,15 @@
+# file : makefile
+# author : Boris Kolpackov <boris@kolpackov.net>
+# copyright : Copyright (c) 2005-2010 Boris Kolpackov
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))build/bootstrap.make
+
+default := $(out_base)/
+clean := $(out_base)/.clean
+
+$(default): $(out_base)/cult/ $(out_base)/examples/
+$(clean): $(out_base)/cult/.clean $(out_base)/examples/.clean
+
+$(call import,$(src_base)/cult/makefile)
+$(call import,$(src_base)/examples/makefile)
diff --git a/libcult/version b/libcult/version
new file mode 100644
index 0000000..c514bd8
--- /dev/null
+++ b/libcult/version
@@ -0,0 +1 @@
+1.4.6